Commit | Line | Data |
---|---|---|
546a1ecc TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
bc77d7c0 | 4 | | Copyright CiviCRM LLC. All rights reserved. | |
546a1ecc | 5 | | | |
bc77d7c0 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 | ||
12 | use Civi\ActionSchedule\RecipientBuilder; | |
13 | ||
14 | /** | |
15 | * Class CRM_Event_ActionMapping | |
16 | * | |
17 | * This defines the scheduled-reminder functionality for CiviEvent | |
18 | * participants. It allows one to target messages on the | |
19 | * event's start-date/end-date, with additional filtering by | |
20 | * event-type, event-template, or event-id. | |
21 | */ | |
22 | class CRM_Event_ActionMapping extends \Civi\ActionSchedule\Mapping { | |
23 | ||
46f5566c TO |
24 | /** |
25 | * The value for civicrm_action_schedule.mapping_id which identifies the | |
26 | * "Event Type" mapping. | |
27 | * | |
28 | * Note: This value is chosen to match legacy DB IDs. | |
29 | */ | |
30 | const EVENT_TYPE_MAPPING_ID = 2; | |
31 | const EVENT_NAME_MAPPING_ID = 3; | |
32 | const EVENT_TPL_MAPPING_ID = 5; | |
33 | ||
34 | /** | |
35 | * Register CiviEvent-related action mappings. | |
36 | * | |
37 | * @param \Civi\ActionSchedule\Event\MappingRegisterEvent $registrations | |
38 | */ | |
39 | public static function onRegisterActionMappings(\Civi\ActionSchedule\Event\MappingRegisterEvent $registrations) { | |
be2fb01f | 40 | $registrations->register(CRM_Event_ActionMapping::create([ |
46f5566c TO |
41 | 'id' => CRM_Event_ActionMapping::EVENT_TYPE_MAPPING_ID, |
42 | 'entity' => 'civicrm_participant', | |
43 | 'entity_label' => ts('Event Type'), | |
44 | 'entity_value' => 'event_type', | |
45 | 'entity_value_label' => ts('Event Type'), | |
46 | 'entity_status' => 'civicrm_participant_status_type', | |
47 | 'entity_status_label' => ts('Participant Status'), | |
be2fb01f CW |
48 | ])); |
49 | $registrations->register(CRM_Event_ActionMapping::create([ | |
46f5566c TO |
50 | 'id' => CRM_Event_ActionMapping::EVENT_NAME_MAPPING_ID, |
51 | 'entity' => 'civicrm_participant', | |
52 | 'entity_label' => ts('Event Name'), | |
53 | 'entity_value' => 'civicrm_event', | |
54 | 'entity_value_label' => ts('Event Name'), | |
55 | 'entity_status' => 'civicrm_participant_status_type', | |
56 | 'entity_status_label' => ts('Participant Status'), | |
be2fb01f CW |
57 | ])); |
58 | $registrations->register(CRM_Event_ActionMapping::create([ | |
46f5566c TO |
59 | 'id' => CRM_Event_ActionMapping::EVENT_TPL_MAPPING_ID, |
60 | 'entity' => 'civicrm_participant', | |
61 | 'entity_label' => ts('Event Template'), | |
62 | 'entity_value' => 'event_template', | |
63 | 'entity_value_label' => ts('Event Template'), | |
64 | 'entity_status' => 'civicrm_participant_status_type', | |
65 | 'entity_status_label' => ts('Participant Status'), | |
be2fb01f | 66 | ])); |
46f5566c TO |
67 | } |
68 | ||
9f1cadce JP |
69 | /** |
70 | * Get a list of available date fields. | |
71 | * | |
72 | * @return array | |
73 | * Array(string $fieldName => string $fieldLabel). | |
74 | */ | |
75 | public function getDateFields() { | |
be2fb01f | 76 | return [ |
8a4b89b4 LS |
77 | 'start_date' => ts('Event Start'), |
78 | 'end_date' => ts('Event End'), | |
79 | 'registration_start_date' => ts('Registration Start'), | |
80 | 'registration_end_date' => ts('Registration End'), | |
be2fb01f | 81 | ]; |
9f1cadce JP |
82 | } |
83 | ||
0effed37 TO |
84 | /** |
85 | * Get a list of recipient types. | |
86 | * | |
87 | * Note: A single schedule may filter on *zero* or *one* recipient types. | |
88 | * When an admin chooses a value, it's stored in $schedule->recipient. | |
89 | * | |
90 | * @return array | |
91 | * array(string $value => string $label). | |
92 | * Ex: array('assignee' => 'Activity Assignee'). | |
93 | */ | |
94 | public function getRecipientTypes() { | |
95 | return \CRM_Core_OptionGroup::values('event_contacts', FALSE, FALSE, FALSE, NULL, 'label', TRUE, FALSE, 'name'); | |
96 | } | |
97 | ||
98 | /** | |
99 | * Get a list of recipients which match the given type. | |
100 | * | |
101 | * Note: A single schedule may filter on *multiple* recipients. | |
102 | * When an admin chooses value(s), it's stored in $schedule->recipient_listing. | |
103 | * | |
104 | * @param string $recipientType | |
105 | * Ex: 'participant_role'. | |
106 | * @return array | |
107 | * Array(mixed $name => string $label). | |
108 | * Ex: array(1 => 'Attendee', 2 => 'Volunteer'). | |
109 | * @see getRecipientTypes | |
110 | */ | |
111 | public function getRecipientListing($recipientType) { | |
112 | switch ($recipientType) { | |
113 | case 'participant_role': | |
114 | return \CRM_Event_PseudoConstant::participantRole(); | |
115 | ||
116 | default: | |
be2fb01f | 117 | return []; |
0effed37 TO |
118 | } |
119 | } | |
120 | ||
546a1ecc TO |
121 | /** |
122 | * Generate a query to locate recipients who match the given | |
123 | * schedule. | |
124 | * | |
125 | * @param \CRM_Core_DAO_ActionSchedule $schedule | |
126 | * The schedule as configured by the administrator. | |
127 | * @param string $phase | |
128 | * See, e.g., RecipientBuilder::PHASE_RELATION_FIRST. | |
ad37ac8e | 129 | * @param array $defaultParams |
130 | * | |
546a1ecc TO |
131 | * @return \CRM_Utils_SQL_Select |
132 | * @see RecipientBuilder | |
133 | */ | |
efc40454 | 134 | public function createQuery($schedule, $phase, $defaultParams) { |
546a1ecc TO |
135 | $selectedValues = (array) \CRM_Utils_Array::explodePadded($schedule->entity_value); |
136 | $selectedStatuses = (array) \CRM_Utils_Array::explodePadded($schedule->entity_status); | |
137 | ||
fe7f4414 | 138 | $query = \CRM_Utils_SQL_Select::from("{$this->entity} e")->param($defaultParams); |
546a1ecc TO |
139 | $query['casAddlCheckFrom'] = 'civicrm_event r'; |
140 | $query['casContactIdField'] = 'e.contact_id'; | |
141 | $query['casEntityIdField'] = 'e.id'; | |
142 | $query['casContactTableAlias'] = NULL; | |
143 | $query['casDateField'] = str_replace('event_', 'r.', $schedule->start_action_date); | |
ba6673f6 | 144 | if (empty($query['casDateField']) && $schedule->absolute_date) { |
e08fae02 | 145 | $query['casDateField'] = "'" . CRM_Utils_Type::escape($schedule->absolute_date, 'String') . "'"; |
ba6673f6 | 146 | } |
546a1ecc TO |
147 | |
148 | $query->join('r', 'INNER JOIN civicrm_event r ON e.event_id = r.id'); | |
149 | if ($schedule->recipient_listing && $schedule->limit_to) { | |
673c1c81 | 150 | switch ($schedule->recipient) { |
546a1ecc TO |
151 | case 'participant_role': |
152 | $query->where("e.role_id IN (#recipList)") | |
153 | ->param('recipList', \CRM_Utils_Array::explodePadded($schedule->recipient_listing)); | |
154 | break; | |
155 | ||
156 | default: | |
157 | break; | |
158 | } | |
159 | } | |
160 | ||
161 | // build where clause | |
3741f351 | 162 | // FIXME: This handles scheduled reminder of type "Event Name" and "Event Type", gives incorrect result on "Event Template". |
546a1ecc | 163 | if (!empty($selectedValues)) { |
46f5566c | 164 | $valueField = ($this->id == \CRM_Event_ActionMapping::EVENT_TYPE_MAPPING_ID) ? 'event_type_id' : 'id'; |
546a1ecc TO |
165 | $query->where("r.{$valueField} IN (@selectedValues)") |
166 | ->param('selectedValues', $selectedValues); | |
167 | } | |
168 | else { | |
46f5566c | 169 | $query->where(($this->id == \CRM_Event_ActionMapping::EVENT_TYPE_MAPPING_ID) ? "r.event_type_id IS NULL" : "r.id IS NULL"); |
546a1ecc TO |
170 | } |
171 | ||
172 | $query->where('r.is_active = 1'); | |
173 | $query->where('r.is_template = 0'); | |
174 | ||
175 | // participant status criteria not to be implemented for additional recipients | |
673c1c81 | 176 | // ... why not? |
546a1ecc TO |
177 | if (!empty($selectedStatuses)) { |
178 | switch ($phase) { | |
179 | case RecipientBuilder::PHASE_RELATION_FIRST: | |
180 | case RecipientBuilder::PHASE_RELATION_REPEAT: | |
181 | $query->where("e.status_id IN (#selectedStatuses)") | |
182 | ->param('selectedStatuses', $selectedStatuses); | |
183 | break; | |
184 | ||
185 | } | |
186 | } | |
187 | return $query; | |
188 | } | |
189 | ||
3741f351 JG |
190 | /** |
191 | * Determine whether a schedule based on this mapping should | |
192 | * send to additional contacts. | |
193 | * | |
194 | * @param string $entityId Either an event ID/event type ID, or a set of event IDs/types separated | |
195 | * by the separation character. | |
196 | */ | |
197 | public function sendToAdditional($entityId): bool { | |
198 | $selectedValues = (array) \CRM_Utils_Array::explodePadded($entityId); | |
199 | switch ($this->id) { | |
200 | case self::EVENT_TYPE_MAPPING_ID: | |
201 | $valueTable = 'e'; | |
202 | $valueField = 'event_type_id'; | |
203 | $templateReminder = FALSE; | |
204 | break; | |
205 | ||
206 | case self::EVENT_NAME_MAPPING_ID: | |
207 | $valueTable = 'e'; | |
208 | $valueField = 'id'; | |
209 | $templateReminder = FALSE; | |
210 | break; | |
211 | ||
212 | case self::EVENT_TPL_MAPPING_ID: | |
213 | $valueTable = 't'; | |
214 | $valueField = 'id'; | |
215 | $templateReminder = TRUE; | |
216 | break; | |
217 | } | |
218 | // Don't send to additional recipients if this event is deleted or a template. | |
219 | $query = new \CRM_Utils_SQL_Select('civicrm_event e'); | |
220 | $query | |
221 | ->select('e.id') | |
222 | ->where("e.is_template = 0") | |
223 | ->where("e.is_active = 1"); | |
224 | if ($templateReminder) { | |
225 | $query->join('r', 'INNER JOIN civicrm_event t ON e.template_title = t.template_title AND t.is_template = 1'); | |
226 | } | |
227 | $sql = $query | |
228 | ->where("{$valueTable}.{$valueField} IN (@selectedValues)") | |
229 | ->param('selectedValues', $selectedValues) | |
230 | ->toSQL(); | |
231 | $dao = \CRM_Core_DAO::executeQuery($sql); | |
232 | return (bool) $dao->N; | |
233 | } | |
234 | ||
546a1ecc | 235 | } |