Merge pull request #24027 from totten/master552-status-footer-skipsort
[civicrm-core.git] / CRM / Core / Task.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
10 */
11
12 /**
13 * @package CRM
14 * @copyright CiviCRM LLC https://civicrm.org/licensing
15 */
16
17 /**
18 * Class to represent the actions that can be performed on a group of contacts used by the search forms.
19 */
20 abstract class CRM_Core_Task {
21
22 /**
23 * These constants are only used as enumerators for each of the batch tasks.
24 */
25 const
26 // General (Implemented by more than one entity)
27 GROUP_REMOVE = 1,
28 GROUP_ADD = 2,
29 PDF_LETTER = 3,
30 TASK_DELETE = 4,
31 TASK_PRINT = 5,
32 BATCH_UPDATE = 6,
33 TASK_SMS = 7,
34 TASK_EXPORT = 8,
35 TASK_EMAIL = 9,
36 TAG_ADD = 10,
37 TAG_REMOVE = 11,
38 // Contact tasks
39 SAVE_SEARCH = 12,
40 SAVE_SEARCH_UPDATE = 13,
41 CREATE_MAILING = 14,
42 DELETE_PERMANENTLY = 15,
43 LABEL_CONTACTS = 16;
44
45 /**
46 * The task array
47 *
48 * @var array
49 */
50 public static $_tasks = [];
51
52 /**
53 * @var string
54 * This must be defined in each child class. It is passed to the searchTasks hook.
55 * Example: $objectType = 'event';
56 */
57 public static $objectType = NULL;
58
59 /**
60 * Generates a list of batch tasks available for the current entities.
61 * Each child class should populate $_tasks array and then call this parent function for shared functionality.
62 * * @return array The set of tasks for a group of contacts
63 * [ 'title' => The Task title,
64 * 'class' => The Task Form class name,
65 * 'result => Boolean. FIXME: Not sure what this is for
66 * ]
67 */
68 public static function tasks() {
69 CRM_Utils_Hook::searchTasks(static::$objectType, self::$_tasks);
70 asort(self::$_tasks);
71
72 return self::$_tasks;
73 }
74
75 /**
76 * These tasks are the core set of tasks that the user can perform
77 * on a contact / group of contacts
78 *
79 * @return array
80 * the set of tasks for a group of contacts
81 */
82 public static function taskTitles() {
83 static::tasks();
84
85 $titles = [];
86 foreach (self::$_tasks as $id => $value) {
87 $titles[$id] = $value['title'];
88 }
89
90 if (!CRM_Utils_Mail::validOutBoundMail()) {
91 unset($titles[self::TASK_EMAIL]);
92 unset($titles[self::CREATE_MAILING]);
93 }
94
95 // Users who do not have 'access deleted contacts' should NOT have the 'Delete Permanently' option in search result tasks
96 if (!CRM_Core_Permission::check('access deleted contacts') ||
97 !CRM_Core_Permission::check('delete contacts')
98 ) {
99 unset($titles[self::DELETE_PERMANENTLY]);
100 }
101 return $titles;
102 }
103
104 /**
105 * Show tasks selectively based on the permission level
106 * of the user
107 * This function should be overridden by the child class which would normally call parent::corePermissionedTaskTitles
108 *
109 * @param int $permission
110 * @param array $params
111 * "ssID: Saved Search ID": If !empty we are in saved search context
112 *
113 * @return array
114 * set of tasks that are valid for the user
115 */
116 public static function permissionedTaskTitles($permission, $params) {
117 return self::corePermissionedTaskTitles(self::tasks(), $permission, $params);
118 }
119
120 /**
121 * Show tasks selectively based on the permission level
122 * of the user
123 * This function should be called by permissionedTaskTitles in children
124 *
125 * @param array $tasks The array of tasks generated by permissionedTaskTitles
126 * @param int $permission
127 * @param array $params
128 * "ssID: Saved Search ID": If !empty we are in saved search context
129 *
130 * @return array
131 * set of tasks that are valid for the user
132 */
133 public static function corePermissionedTaskTitles($tasks, $permission, $params) {
134 // Only offer the "Update Smart Group" task if a smart group/saved search is already in play and we have edit permissions
135 if (!empty($params['ssID']) && ($permission == CRM_Core_Permission::EDIT) && CRM_Core_Permission::check('edit groups')) {
136 $tasks[self::SAVE_SEARCH_UPDATE] = self::$_tasks[self::SAVE_SEARCH_UPDATE]['title'];
137 }
138 else {
139 unset($tasks[self::SAVE_SEARCH_UPDATE]);
140 }
141
142 asort($tasks);
143 return $tasks;
144 }
145
146 /**
147 * These tasks are the core set of tasks that the user can perform
148 * on participants
149 *
150 * @param int $value
151 *
152 * @return array
153 * the set of tasks for a group of participants
154 */
155 public static function getTask($value) {
156 static::tasks();
157
158 if (empty(self::$_tasks[$value])) {
159 // Children can specify a default task (eg. print), pick another if it is not valid.
160 $value = key(self::$_tasks);
161 }
162 return [
163 CRM_Utils_Array::value('class', self::$_tasks[$value]),
164 CRM_Utils_Array::value('result', self::$_tasks[$value]),
165 ];
166 }
167
168 /**
169 * Filter tasks based on the permission key, if available.
170 *
171 * @param array $tasks
172 * @param bool $hasEditContactPermission
173 * Does the user have permission to edit the given contact. Required where
174 * permission to edit the user is required in conjunction with permission
175 * to do the task.
176 *
177 * @return array
178 */
179 protected static function getTasksFilteredByPermission(array $tasks, bool $hasEditContactPermission): array {
180 foreach ($tasks as $index => $task) {
181 // requires_edit_contact_permission is a (hopefully transient way) of denoting which
182 // tasks need 'edit this contact' on top of the membership permission.
183 if (!empty($task['requires_edit_contact_permission']) && !$hasEditContactPermission) {
184 unset($tasks[$index]);
185 }
186 elseif (!empty($task['permissions']) && !CRM_Core_Permission::check($task['permissions'])) {
187 unset($tasks[$index]);
188 }
189 }
190 return $tasks;
191 }
192
193 /**
194 * Get task tiles filtered by any declared permissions.
195 *
196 * @param array $tasks
197 * @param bool $hasEditContactPermission
198 * Does the user have permission to edit the given contact. Required where
199 * permission to edit the user is required in conjunction with permission
200 * to do the task.
201 *
202 * @return array
203 */
204 protected static function getTitlesFilteredByPermission(array $tasks, bool $hasEditContactPermission): array {
205 $availableTasks = self::getTasksFilteredByPermission($tasks, $hasEditContactPermission);
206 $return = [];
207 foreach ($availableTasks as $key => $details) {
208 $return[$key] = $details['title'];
209 }
210 return $return;
211 }
212
213 /**
214 * Function to return the task information on basis of provided task's form name
215 *
216 * @param string $className
217 *
218 * @return array [ 0 => Task ID, 1 => Task Title ]
219 */
220 public static function getTaskAndTitleByClass($className) {
221 static::tasks();
222
223 foreach (self::$_tasks as $task => $value) {
224 if ((!empty($value['url']) || $task == self::TASK_EXPORT)
225 && ((is_array($value['class']) && in_array($className, $value['class']))
226 || ($value['class'] == $className))) {
227 return [$task, CRM_Utils_Array::value('title', $value)];
228 }
229 }
230 return [];
231 }
232
233 }