Commit | Line | Data |
---|---|---|
50a23755 | 1 | <?php |
546a1ecc TO |
2 | /* |
3 | +--------------------------------------------------------------------+ | |
41498ac5 | 4 | | Copyright CiviCRM LLC. All rights reserved. | |
546a1ecc | 5 | | | |
41498ac5 TO |
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 | | |
546a1ecc TO |
9 | +--------------------------------------------------------------------+ |
10 | */ | |
11 | ||
50a23755 TO |
12 | namespace Civi\ActionSchedule; |
13 | ||
546a1ecc TO |
14 | /** |
15 | * Class Mapping | |
16 | * @package Civi\ActionSchedule | |
17 | * | |
18 | * This is the initial implementation of MappingInterface; it was | |
19 | * constructed by cutting out swaths from CRM_Core_BAO_ActionSchedule. | |
20 | * New implementers should consider implementing MappingInterface on | |
21 | * their own. | |
22 | * | |
23 | * Background: The original designers of ActionMappings intended that | |
24 | * one could create and configure new mappings through the database. | |
25 | * To, e.g., define the filtering options for CiviEvent, you | |
26 | * would insert a record in "civicrm_action_mapping" with fields like | |
27 | * "entity" (a table name, eg "civicrm_event"), "entity_value" (an | |
28 | * option-group name, eg "event_types"). | |
29 | * | |
30 | * Unfortunately, the metadata in "civicrm_action_mapping" proved | |
31 | * inadequate and was not updated to cope. Instead, a number | |
32 | * of work-arounds for specific entities were hard-coded into | |
33 | * the core action-scheduling code. Ultimately, to add a new | |
34 | * mapping type, one needed to run around and patch a dozen | |
35 | * places. | |
36 | * | |
37 | * The new MappingInterface makes no pretense of database-driven | |
38 | * configuration. The dozen places have been consolidated and | |
39 | * replaced with functions in MappingInterface. | |
40 | * | |
9e1bf145 | 41 | * This "Mapping" implementation is a refactoring of the old |
546a1ecc TO |
42 | * hard-coded bits. Internally, it uses the concepts from |
43 | * "civicrm_action_mapping". The resulting code is more | |
9e1bf145 TO |
44 | * convoluted than a clean implementation of MappingInterface, but |
45 | * it strictly matches the old behavior (based on logging/comparing | |
46 | * the queries produced through ActionScheduleTest). | |
546a1ecc TO |
47 | */ |
48 | abstract class Mapping implements MappingInterface { | |
50a23755 | 49 | |
c64f69d9 | 50 | private static $fields = [ |
50a23755 TO |
51 | 'id', |
52 | 'entity', | |
53 | 'entity_label', | |
54 | 'entity_value', | |
55 | 'entity_value_label', | |
56 | 'entity_status', | |
57 | 'entity_status_label', | |
58 | 'entity_date_start', | |
59 | 'entity_date_end', | |
c64f69d9 | 60 | ]; |
50a23755 | 61 | |
e8e8f3ad | 62 | /** |
63 | * Create mapping. | |
64 | * | |
65 | * @param array $params | |
66 | * | |
67 | * @return static | |
68 | */ | |
50a23755 TO |
69 | public static function create($params) { |
70 | return new static($params); | |
71 | } | |
72 | ||
e8e8f3ad | 73 | /** |
74 | * Class constructor. | |
75 | * | |
76 | * @param array $params | |
77 | */ | |
50a23755 TO |
78 | public function __construct($params) { |
79 | foreach (self::$fields as $field) { | |
80 | if (isset($params[$field])) { | |
81 | $this->{$field} = $params[$field]; | |
82 | } | |
83 | } | |
84 | } | |
85 | ||
9e1bf145 | 86 | protected $id; |
50a23755 TO |
87 | |
88 | /** | |
89 | * The basic entity to query (table name). | |
90 | * | |
91 | * @var string | |
92 | * Ex: 'civicrm_activity', 'civicrm_event'. | |
93 | */ | |
9e1bf145 | 94 | protected $entity; |
50a23755 TO |
95 | |
96 | /** | |
97 | * The basic entity to query (label). | |
98 | * | |
34f3bbd9 | 99 | * @var string |
50a23755 TO |
100 | * Ex: 'Activity', 'Event' |
101 | */ | |
9e1bf145 | 102 | private $entity_label; |
50a23755 TO |
103 | |
104 | /** | |
105 | * Level 1 filter -- the field/option-list to filter on. | |
106 | * | |
107 | * @var string | |
108 | * Ex: 'activity_type', 'civicrm_event', 'event_template'. | |
109 | */ | |
77e16391 | 110 | private $entity_value; |
50a23755 TO |
111 | |
112 | /** | |
113 | * Level 1 filter -- The field label. | |
114 | * | |
115 | * @var string | |
116 | * Ex: 'Activity Type', 'Event Name', 'Event Template'. | |
117 | */ | |
9e1bf145 | 118 | private $entity_value_label; |
50a23755 TO |
119 | |
120 | /** | |
121 | * Level 2 filter -- the field/option-list to filter on. | |
122 | * @var string | |
123 | * Ex: 'activity_status, 'civicrm_participant_status_type', 'auto_renew_options'. | |
124 | */ | |
9e1bf145 | 125 | private $entity_status; |
50a23755 TO |
126 | |
127 | /** | |
128 | * Level 2 filter -- the field label. | |
129 | * @var string | |
130 | * Ex: 'Activity Status', 'Participant Status', 'Auto Rewnewal Options'. | |
131 | */ | |
9e1bf145 | 132 | private $entity_status_label; |
50a23755 TO |
133 | |
134 | /** | |
135 | * Date filter -- the field name. | |
cc101011 | 136 | * @var string|null |
50a23755 TO |
137 | * Ex: 'event_start_date' |
138 | */ | |
9e1bf145 | 139 | private $entity_date_start; |
50a23755 TO |
140 | |
141 | /** | |
142 | * Date filter -- the field name. | |
cc101011 | 143 | * @var string|null |
50a23755 TO |
144 | * Ex: 'event_end_date'. |
145 | */ | |
9e1bf145 | 146 | private $entity_date_end; |
50a23755 | 147 | |
9e1bf145 TO |
148 | /** |
149 | * @return mixed | |
150 | */ | |
151 | public function getId() { | |
152 | return $this->id; | |
153 | } | |
154 | ||
155 | /** | |
156 | * @return string | |
157 | */ | |
158 | public function getEntity() { | |
159 | return $this->entity; | |
160 | } | |
161 | ||
162 | /** | |
163 | * Get a printable label for this mapping type. | |
164 | * | |
165 | * @return string | |
166 | */ | |
167 | public function getLabel() { | |
168 | return $this->entity_label; | |
169 | } | |
170 | ||
171 | /** | |
172 | * Get a printable label to use a header on the 'value' filter. | |
173 | * | |
174 | * @return string | |
175 | */ | |
176 | public function getValueHeader() { | |
177 | return $this->entity_value_label; | |
178 | } | |
179 | ||
180 | /** | |
181 | * Get a printable label to use a header on the 'status' filter. | |
182 | * | |
183 | * @return string | |
184 | */ | |
185 | public function getStatusHeader() { | |
186 | return $this->entity_status_label; | |
187 | } | |
50a23755 TO |
188 | |
189 | /** | |
190 | * Get a list of value options. | |
191 | * | |
192 | * @return array | |
193 | * Array(string $value => string $label). | |
194 | * Ex: array(123 => 'Phone Call', 456 => 'Meeting'). | |
195 | */ | |
196 | public function getValueLabels() { | |
197 | return self::getValueLabelMap($this->entity_value); | |
198 | } | |
199 | ||
200 | /** | |
201 | * Get a list of status options. | |
202 | * | |
203 | * @param string|int $value | |
204 | * The list of status options may be contingent upon the selected filter value. | |
205 | * This is the selected filter value. | |
206 | * @return array | |
207 | * Array(string $value => string $label). | |
208 | * Ex: Array(123 => 'Completed', 456 => 'Scheduled'). | |
209 | */ | |
210 | public function getStatusLabels($value) { | |
211 | if ($this->entity_status === 'auto_renew_options') { | |
212 | if ($value && \CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', $value, 'auto_renew')) { | |
213 | return \CRM_Core_OptionGroup::values('auto_renew_options'); | |
214 | } | |
215 | else { | |
c64f69d9 | 216 | return []; |
50a23755 TO |
217 | } |
218 | } | |
219 | return self::getValueLabelMap($this->entity_status); | |
220 | } | |
221 | ||
222 | /** | |
546a1ecc TO |
223 | * Get a list of available date fields. |
224 | * | |
50a23755 TO |
225 | * @return array |
226 | * Array(string $fieldName => string $fieldLabel). | |
227 | */ | |
228 | public function getDateFields() { | |
c64f69d9 | 229 | $dateFieldLabels = []; |
50a23755 TO |
230 | if (!empty($this->entity_date_start)) { |
231 | $dateFieldLabels[$this->entity_date_start] = ucwords(str_replace('_', ' ', $this->entity_date_start)); | |
232 | } | |
233 | if (!empty($this->entity_date_end)) { | |
234 | $dateFieldLabels[$this->entity_date_end] = ucwords(str_replace('_', ' ', $this->entity_date_end)); | |
235 | } | |
236 | return $dateFieldLabels; | |
237 | } | |
238 | ||
546a1ecc | 239 | /** |
0effed37 | 240 | * Get a list of recipient types. |
9d97a648 | 241 | * |
0effed37 TO |
242 | * Note: A single schedule may filter on *zero* or *one* recipient types. |
243 | * When an admin chooses a value, it's stored in $schedule->recipient. | |
546a1ecc | 244 | * |
546a1ecc | 245 | * @return array |
0effed37 TO |
246 | * array(string $value => string $label). |
247 | * Ex: array('assignee' => 'Activity Assignee'). | |
546a1ecc | 248 | */ |
0effed37 | 249 | public function getRecipientTypes() { |
c64f69d9 | 250 | return []; |
77e16391 TO |
251 | } |
252 | ||
50a23755 | 253 | /** |
0effed37 | 254 | * Get a list of recipients which match the given type. |
9d97a648 | 255 | * |
0effed37 TO |
256 | * Note: A single schedule may filter on *multiple* recipients. |
257 | * When an admin chooses value(s), it's stored in $schedule->recipient_listing. | |
546a1ecc | 258 | * |
0effed37 TO |
259 | * @param string $recipientType |
260 | * Ex: 'participant_role'. | |
50a23755 | 261 | * @return array |
0effed37 TO |
262 | * Array(mixed $name => string $label). |
263 | * Ex: array(1 => 'Attendee', 2 => 'Volunteer'). | |
264 | * @see getRecipientTypes | |
50a23755 | 265 | */ |
0effed37 | 266 | public function getRecipientListing($recipientType) { |
c64f69d9 | 267 | return []; |
50a23755 TO |
268 | } |
269 | ||
270 | protected static function getValueLabelMap($name) { | |
271 | static $valueLabelMap = NULL; | |
272 | if ($valueLabelMap === NULL) { | |
4efde586 | 273 | // CRM-20510: Include CiviCampaign activity types along with CiviCase IF component is enabled |
274 | $valueLabelMap['activity_type'] = \CRM_Core_PseudoConstant::activityType(TRUE, TRUE, FALSE, 'label', TRUE); | |
50a23755 TO |
275 | asort($valueLabelMap['activity_type']); |
276 | ||
277 | $valueLabelMap['activity_status'] = \CRM_Core_PseudoConstant::activityStatus(); | |
278 | $valueLabelMap['event_type'] = \CRM_Event_PseudoConstant::eventType(); | |
279 | $valueLabelMap['civicrm_event'] = \CRM_Event_PseudoConstant::event(NULL, FALSE, "( is_template IS NULL OR is_template != 1 )"); | |
280 | $valueLabelMap['civicrm_participant_status_type'] = \CRM_Event_PseudoConstant::participantStatus(NULL, NULL, 'label'); | |
281 | $valueLabelMap['event_template'] = \CRM_Event_PseudoConstant::eventTemplates(); | |
282 | $valueLabelMap['auto_renew_options'] = \CRM_Core_OptionGroup::values('auto_renew_options'); | |
283 | $valueLabelMap['contact_date_reminder_options'] = \CRM_Core_OptionGroup::values('contact_date_reminder_options'); | |
284 | $valueLabelMap['civicrm_membership_type'] = \CRM_Member_PseudoConstant::membershipType(); | |
285 | ||
286 | $allCustomFields = \CRM_Core_BAO_CustomField::getFields(''); | |
c64f69d9 | 287 | $dateFields = [ |
50a23755 TO |
288 | 'birth_date' => ts('Birth Date'), |
289 | 'created_date' => ts('Created Date'), | |
290 | 'modified_date' => ts('Modified Date'), | |
c64f69d9 | 291 | ]; |
50a23755 TO |
292 | foreach ($allCustomFields as $fieldID => $field) { |
293 | if ($field['data_type'] == 'Date') { | |
294 | $dateFields["custom_$fieldID"] = $field['label']; | |
295 | } | |
296 | } | |
297 | $valueLabelMap['civicrm_contact'] = $dateFields; | |
298 | } | |
299 | ||
300 | return $valueLabelMap[$name]; | |
301 | } | |
302 | ||
7f0141d8 TO |
303 | /** |
304 | * Determine whether a schedule based on this mapping is sufficiently | |
305 | * complete. | |
306 | * | |
307 | * @param \CRM_Core_DAO_ActionSchedule $schedule | |
308 | * @return array | |
309 | * Array (string $code => string $message). | |
310 | * List of error messages. | |
311 | */ | |
312 | public function validateSchedule($schedule) { | |
c64f69d9 | 313 | return []; |
7f0141d8 TO |
314 | } |
315 | ||
546a1ecc TO |
316 | /** |
317 | * Generate a query to locate contacts who match the given | |
318 | * schedule. | |
319 | * | |
320 | * @param \CRM_Core_DAO_ActionSchedule $schedule | |
321 | * @param string $phase | |
322 | * See, e.g., RecipientBuilder::PHASE_RELATION_FIRST. | |
efc40454 | 323 | * @param array $defaultParams |
546a1ecc TO |
324 | * @return \CRM_Utils_SQL_Select |
325 | */ | |
34f3bbd9 | 326 | abstract public function createQuery($schedule, $phase, $defaultParams); |
546a1ecc | 327 | |
e08fae02 PH |
328 | /** |
329 | * Determine whether a schedule based on this mapping should | |
330 | * reset the reminder state if the trigger date changes. | |
331 | * | |
332 | * @return bool | |
333 | * | |
334 | * @param \CRM_Core_DAO_ActionSchedule $schedule | |
335 | */ | |
336 | public function resetOnTriggerDateChange($schedule) { | |
337 | return FALSE; | |
338 | } | |
339 | ||
3741f351 JG |
340 | /** |
341 | * Determine whether a schedule based on this mapping should | |
342 | * send to additional contacts. | |
343 | */ | |
344 | abstract public function sendToAdditional($entityId): bool; | |
345 | ||
50a23755 | 346 | } |