PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/sites/all/modules/contrib/civicrm/CRM/Core/Action.php

https://gitlab.com/virtualrealms/d7civicrm
PHP | 408 lines | 213 code | 33 blank | 162 comment | 40 complexity | a7065651184df87e689b32a24e7be611 MD5 | raw file
  1. <?php
  2. /*
  3. +--------------------------------------------------------------------+
  4. | CiviCRM version 5 |
  5. +--------------------------------------------------------------------+
  6. | Copyright CiviCRM LLC (c) 2004-2019 |
  7. +--------------------------------------------------------------------+
  8. | This file is a part of CiviCRM. |
  9. | |
  10. | CiviCRM is free software; you can copy, modify, and distribute it |
  11. | under the terms of the GNU Affero General Public License |
  12. | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
  13. | |
  14. | CiviCRM is distributed in the hope that it will be useful, but |
  15. | WITHOUT ANY WARRANTY; without even the implied warranty of |
  16. | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
  17. | See the GNU Affero General Public License for more details. |
  18. | |
  19. | You should have received a copy of the GNU Affero General Public |
  20. | License and the CiviCRM Licensing Exception along |
  21. | with this program; if not, contact CiviCRM LLC |
  22. | at info[AT]civicrm[DOT]org. If you have questions about the |
  23. | GNU Affero General Public License or the licensing of CiviCRM, |
  24. | see the CiviCRM license FAQ at http://civicrm.org/licensing |
  25. +--------------------------------------------------------------------+
  26. */
  27. /**
  28. * The core concept of the system is an action performed on an object. Typically this will be a "data model" object
  29. * as specified in the API specs. We attempt to keep the number and type of actions consistent
  30. * and similar across all objects (thus providing both reuse and standards)
  31. *
  32. * @package CRM
  33. * @copyright CiviCRM LLC (c) 2004-2019
  34. * $Id$
  35. *
  36. */
  37. class CRM_Core_Action {
  38. /**
  39. * Different possible actions are defined here. Keep in sync with the
  40. * constant from CRM_Core_Form for various modes.
  41. *
  42. * @var int
  43. */
  44. const
  45. NONE = 0,
  46. ADD = 1,
  47. UPDATE = 2,
  48. VIEW = 4,
  49. DELETE = 8,
  50. BROWSE = 16,
  51. ENABLE = 32,
  52. DISABLE = 64,
  53. EXPORT = 128,
  54. BASIC = 256,
  55. ADVANCED = 512,
  56. PREVIEW = 1024,
  57. FOLLOWUP = 2048,
  58. MAP = 4096,
  59. PROFILE = 8192,
  60. COPY = 16384,
  61. RENEW = 32768,
  62. DETACH = 65536,
  63. REVERT = 131072,
  64. CLOSE = 262144,
  65. REOPEN = 524288,
  66. MAX_ACTION = 1048575;
  67. //make sure MAX_ACTION = 2^n - 1 ( n = total number of actions )
  68. /**
  69. * Map the action names to the relevant constant. We perform
  70. * bit manipulation operations so we can perform multiple
  71. * actions on the same object if needed
  72. *
  73. * @var array
  74. *
  75. */
  76. public static $_names = [
  77. 'add' => self::ADD,
  78. 'update' => self::UPDATE,
  79. 'view' => self::VIEW,
  80. 'delete' => self::DELETE,
  81. 'browse' => self::BROWSE,
  82. 'enable' => self::ENABLE,
  83. 'disable' => self::DISABLE,
  84. 'export' => self::EXPORT,
  85. 'preview' => self::PREVIEW,
  86. 'map' => self::MAP,
  87. 'copy' => self::COPY,
  88. 'profile' => self::PROFILE,
  89. 'renew' => self::RENEW,
  90. 'detach' => self::DETACH,
  91. 'revert' => self::REVERT,
  92. 'close' => self::CLOSE,
  93. 'reopen' => self::REOPEN,
  94. ];
  95. /**
  96. * The flipped version of the names array, initialized when used
  97. *
  98. * @var array
  99. */
  100. public static $_description;
  101. /**
  102. * Called by the request object to translate a string into a mask.
  103. *
  104. * @param string $str
  105. * The action to be resolved.
  106. *
  107. * @return int
  108. * the action mask corresponding to the input string
  109. */
  110. public static function resolve($str) {
  111. $action = 0;
  112. if ($str) {
  113. $items = explode('|', $str);
  114. $action = self::map($items);
  115. }
  116. return $action;
  117. }
  118. /**
  119. * Given a string or an array of strings, determine the bitmask
  120. * for this set of actions
  121. *
  122. * @param mixed $item
  123. * Either a single string or an array of strings.
  124. *
  125. * @return int
  126. * the action mask corresponding to the input args
  127. */
  128. public static function map($item) {
  129. $mask = 0;
  130. if (is_array($item)) {
  131. foreach ($item as $it) {
  132. $mask |= self::mapItem($it);
  133. }
  134. return $mask;
  135. }
  136. else {
  137. return self::mapItem($item);
  138. }
  139. }
  140. /**
  141. * Given a string determine the bitmask for this specific string.
  142. *
  143. * @param string $item
  144. * The input action to process.
  145. *
  146. * @return int
  147. * the action mask corresponding to the input string
  148. */
  149. public static function mapItem($item) {
  150. $mask = CRM_Utils_Array::value(trim($item), self::$_names);
  151. return $mask ? $mask : 0;
  152. }
  153. /**
  154. *
  155. * Given an action mask, find the corresponding description
  156. *
  157. * @param int $mask
  158. * The action mask.
  159. *
  160. * @return string
  161. * the corresponding action description
  162. */
  163. public static function description($mask) {
  164. if (!isset(self::$_description)) {
  165. self::$_description = array_flip(self::$_names);
  166. }
  167. return CRM_Utils_Array::value($mask, self::$_description, 'NO DESCRIPTION SET');
  168. }
  169. /**
  170. * Given a set of links and a mask, return the html action string for
  171. * the links associated with the mask
  172. *
  173. * @param array $links
  174. * The set of link items.
  175. * @param int $mask
  176. * The mask to be used. a null mask means all items.
  177. * @param array $values
  178. * The array of values for parameter substitution in the link items.
  179. * @param string $extraULName
  180. * Enclosed extra links in this UL.
  181. * @param bool $enclosedAllInSingleUL
  182. * Force to enclosed all links in single UL.
  183. *
  184. * @param null $op
  185. * @param null $objectName
  186. * @param int $objectId
  187. *
  188. * @return string
  189. * the html string
  190. */
  191. public static function formLink(
  192. $links,
  193. $mask,
  194. $values,
  195. $extraULName = 'more',
  196. $enclosedAllInSingleUL = FALSE,
  197. $op = NULL,
  198. $objectName = NULL,
  199. $objectId = NULL
  200. ) {
  201. if (empty($links)) {
  202. return NULL;
  203. }
  204. // make links indexed sequentially instead of by bitmask
  205. // otherwise it's next to impossible to reliably add new ones
  206. $seqLinks = [];
  207. foreach ($links as $bit => $link) {
  208. $link['bit'] = $bit;
  209. $seqLinks[] = $link;
  210. }
  211. if ($op && $objectName && $objectId) {
  212. CRM_Utils_Hook::links($op, $objectName, $objectId, $seqLinks, $mask, $values);
  213. }
  214. $url = [];
  215. foreach ($seqLinks as $i => $link) {
  216. if (!$mask || !array_key_exists('bit', $link) || ($mask & $link['bit'])) {
  217. $extra = isset($link['extra']) ? self::replace($link['extra'], $values) : NULL;
  218. $frontend = (isset($link['fe'])) ? TRUE : FALSE;
  219. if (isset($link['qs']) && !CRM_Utils_System::isNull($link['qs'])) {
  220. $urlPath = CRM_Utils_System::url(self::replace($link['url'], $values),
  221. self::replace($link['qs'], $values), FALSE, NULL, TRUE, $frontend
  222. );
  223. }
  224. else {
  225. $urlPath = CRM_Utils_Array::value('url', $link, '#');
  226. }
  227. $classes = 'action-item crm-hover-button';
  228. if (isset($link['ref'])) {
  229. $classes .= ' ' . strtolower($link['ref']);
  230. }
  231. //get the user specified classes in.
  232. if (isset($link['class'])) {
  233. $className = is_array($link['class']) ? implode(' ', $link['class']) : $link['class'];
  234. $classes .= ' ' . strtolower($className);
  235. }
  236. if ($urlPath !== '#' && $frontend) {
  237. $extra .= ' target="_blank"';
  238. }
  239. // Hack to make delete dialogs smaller
  240. if (strpos($urlPath, '/delete') || strpos($urlPath, 'action=delete')) {
  241. $classes .= " small-popup";
  242. }
  243. $url[] = sprintf('<a href="%s" class="%s" %s' . $extra . '>%s</a>',
  244. $urlPath,
  245. $classes,
  246. !empty($link['title']) ? "title='{$link['title']}' " : '',
  247. $link['name']
  248. );
  249. }
  250. }
  251. $mainLinks = $url;
  252. if ($enclosedAllInSingleUL) {
  253. $allLinks = '';
  254. CRM_Utils_String::append($allLinks, '</li><li>', $mainLinks);
  255. $allLinks = "{$extraULName}<ul class='panel'><li>{$allLinks}</li></ul>";
  256. $result = "<span class='btn-slide crm-hover-button'>{$allLinks}</span>";
  257. }
  258. else {
  259. $extra = '';
  260. $extraLinks = array_splice($url, 2);
  261. if (count($extraLinks) > 1) {
  262. $mainLinks = array_slice($url, 0, 2);
  263. CRM_Utils_String::append($extra, '</li><li>', $extraLinks);
  264. $extra = "{$extraULName}<ul class='panel'><li>{$extra}</li></ul>";
  265. }
  266. $resultLinks = '';
  267. CRM_Utils_String::append($resultLinks, '', $mainLinks);
  268. if ($extra) {
  269. $result = "<span>{$resultLinks}</span><span class='btn-slide crm-hover-button'>{$extra}</span>";
  270. }
  271. else {
  272. $result = "<span>{$resultLinks}</span>";
  273. }
  274. }
  275. return $result;
  276. }
  277. /**
  278. * Given a set of links and a mask, return a filtered (by mask) array containing the final links with parsed values
  279. * and calling hooks as appropriate.
  280. * Use this when passing a set of action links to the API or to the form without adding html formatting.
  281. *
  282. * @param array $links
  283. * The set of link items.
  284. * @param int $mask
  285. * The mask to be used. a null mask means all items.
  286. * @param array $values
  287. * The array of values for parameter substitution in the link items.
  288. * @param null $op
  289. * @param null $objectName
  290. * @param int $objectId
  291. *
  292. * @return array|null
  293. * The array describing each link
  294. */
  295. public static function filterLinks(
  296. $links,
  297. $mask,
  298. $values,
  299. $op = NULL,
  300. $objectName = NULL,
  301. $objectId = NULL
  302. ) {
  303. if (empty($links)) {
  304. return NULL;
  305. }
  306. // make links indexed sequentially instead of by bitmask
  307. // otherwise it's next to impossible to reliably add new ones
  308. $seqLinks = array();
  309. foreach ($links as $bit => $link) {
  310. $link['bit'] = $bit;
  311. $seqLinks[] = $link;
  312. }
  313. if ($op && $objectName && $objectId) {
  314. CRM_Utils_Hook::links($op, $objectName, $objectId, $seqLinks, $mask, $values);
  315. }
  316. foreach ($seqLinks as $i => $link) {
  317. if (!$mask || !array_key_exists('bit', $link) || ($mask & $link['bit'])) {
  318. $seqLinks[$i]['extra'] = isset($link['extra']) ? self::replace($link['extra'], $values) : NULL;
  319. if (isset($link['qs']) && !CRM_Utils_System::isNull($link['qs'])) {
  320. $seqLinks[$i]['url'] = self::replace($link['url'], $values);
  321. $seqLinks[$i]['qs'] = self::replace($link['qs'], $values);
  322. }
  323. }
  324. else {
  325. unset($seqLinks[$i]);
  326. }
  327. }
  328. return $seqLinks;
  329. }
  330. /**
  331. * Given a string and an array of values, substitute the real values
  332. * in the placeholder in the str in the CiviCRM format
  333. *
  334. * @param string $str
  335. * The string to be replaced.
  336. * @param array $values
  337. * The array of values for parameter substitution in the str.
  338. *
  339. * @return string
  340. * the substituted string
  341. */
  342. public static function &replace(&$str, &$values) {
  343. foreach ($values as $n => $v) {
  344. $str = str_replace("%%$n%%", $v, $str);
  345. }
  346. return $str;
  347. }
  348. /**
  349. * Get the mask for a permission (view, edit or null)
  350. *
  351. * @param array $permissions
  352. *
  353. * @return int
  354. * The mask for the above permission
  355. */
  356. public static function mask($permissions) {
  357. $mask = NULL;
  358. if (!is_array($permissions) || CRM_Utils_System::isNull($permissions)) {
  359. return $mask;
  360. }
  361. //changed structure since we are handling delete separately - CRM-4418
  362. if (in_array(CRM_Core_Permission::VIEW, $permissions)) {
  363. $mask |= self::VIEW | self::EXPORT | self::BASIC | self::ADVANCED | self::BROWSE | self::MAP | self::PROFILE;
  364. }
  365. if (in_array(CRM_Core_Permission::DELETE, $permissions)) {
  366. $mask |= self::DELETE;
  367. }
  368. if (in_array(CRM_Core_Permission::EDIT, $permissions)) {
  369. //make sure we make self::MAX_ACTION = 2^n - 1
  370. //if we add more actions; ( n = total number of actions )
  371. $mask |= (self::MAX_ACTION & ~self::DELETE);
  372. }
  373. return $mask;
  374. }
  375. }