Merge pull request #18411 from MegaphoneJon/pcp-wysiwyg
[civicrm-core.git] / CRM / Event / ActionMapping.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 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
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) {
40 $registrations->register(CRM_Event_ActionMapping::create([
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'),
48 ]));
49 $registrations->register(CRM_Event_ActionMapping::create([
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'),
57 ]));
58 $registrations->register(CRM_Event_ActionMapping::create([
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'),
66 ]));
67 }
68
69 /**
70 * Get a list of available date fields.
71 *
72 * @return array
73 * Array(string $fieldName => string $fieldLabel).
74 */
75 public function getDateFields() {
76 return [
77 'start_date' => ts('Event Start Date'),
78 'end_date' => ts('Event End Date'),
79 'registration_start_date' => ts('Registration Start Date'),
80 'registration_end_date' => ts('Registration End Date'),
81 ];
82 }
83
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:
117 return [];
118 }
119 }
120
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.
129 * @param array $defaultParams
130 *
131 * @return \CRM_Utils_SQL_Select
132 * @see RecipientBuilder
133 */
134 public function createQuery($schedule, $phase, $defaultParams) {
135 $selectedValues = (array) \CRM_Utils_Array::explodePadded($schedule->entity_value);
136 $selectedStatuses = (array) \CRM_Utils_Array::explodePadded($schedule->entity_status);
137
138 $query = \CRM_Utils_SQL_Select::from("{$this->entity} e")->param($defaultParams);
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);
144 if (empty($query['casDateField']) && $schedule->absolute_date) {
145 $query['casDateField'] = "'" . CRM_Utils_Type::escape($schedule->absolute_date, 'String') . "'";
146 }
147
148 $query->join('r', 'INNER JOIN civicrm_event r ON e.event_id = r.id');
149 if ($schedule->recipient_listing && $schedule->limit_to) {
150 switch ($schedule->recipient) {
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
162 // FIXME: This handles scheduled reminder of type "Event Name" and "Event Type", gives incorrect result on "Event Template".
163 if (!empty($selectedValues)) {
164 $valueField = ($this->id == \CRM_Event_ActionMapping::EVENT_TYPE_MAPPING_ID) ? 'event_type_id' : 'id';
165 $query->where("r.{$valueField} IN (@selectedValues)")
166 ->param('selectedValues', $selectedValues);
167 }
168 else {
169 $query->where(($this->id == \CRM_Event_ActionMapping::EVENT_TYPE_MAPPING_ID) ? "r.event_type_id IS NULL" : "r.id IS NULL");
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
176 // ... why not?
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
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
235 }