3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
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 +--------------------------------------------------------------------+
12 use Civi\ActionSchedule\RecipientBuilder
;
15 * Class CRM_Event_ActionMapping
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.
22 class CRM_Event_ActionMapping
extends \Civi\ActionSchedule\Mapping
{
25 * The value for civicrm_action_schedule.mapping_id which identifies the
26 * "Event Type" mapping.
28 * Note: This value is chosen to match legacy DB IDs.
30 const EVENT_TYPE_MAPPING_ID
= 2;
31 const EVENT_NAME_MAPPING_ID
= 3;
32 const EVENT_TPL_MAPPING_ID
= 5;
35 * Register CiviEvent-related action mappings.
37 * @param \Civi\ActionSchedule\Event\MappingRegisterEvent $registrations
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'),
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'),
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'),
70 * Get a list of available date fields.
73 * Array(string $fieldName => string $fieldLabel).
75 public function getDateFields() {
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'),
85 * Get a list of recipient types.
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.
91 * array(string $value => string $label).
92 * Ex: array('assignee' => 'Activity Assignee').
94 public function getRecipientTypes() {
95 return \CRM_Core_OptionGroup
::values('event_contacts', FALSE, FALSE, FALSE, NULL, 'label', TRUE, FALSE, 'name');
99 * Get a list of recipients which match the given type.
101 * Note: A single schedule may filter on *multiple* recipients.
102 * When an admin chooses value(s), it's stored in $schedule->recipient_listing.
104 * @param string $recipientType
105 * Ex: 'participant_role'.
107 * Array(mixed $name => string $label).
108 * Ex: array(1 => 'Attendee', 2 => 'Volunteer').
109 * @see getRecipientTypes
111 public function getRecipientListing($recipientType) {
112 switch ($recipientType) {
113 case 'participant_role':
114 return \CRM_Event_PseudoConstant
::participantRole();
122 * Generate a query to locate recipients who match the given
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
131 * @return \CRM_Utils_SQL_Select
132 * @see RecipientBuilder
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
);
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') . "'";
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 $regex = "([[:cntrl:]]|^)" . implode('([[:cntrl:]]|$)|([[:cntrl:]]|^)', \CRM_Utils_Array
::explodePadded($schedule->recipient_listing
)) . "([[:cntrl:]]|$)";
153 $query->where("e.role_id REGEXP (@regex)")
154 ->param('regex', $regex);
162 // build where clause
163 // FIXME: This handles scheduled reminder of type "Event Name" and "Event Type", gives incorrect result on "Event Template".
164 if (!empty($selectedValues)) {
165 $valueField = ($this->id
== \CRM_Event_ActionMapping
::EVENT_TYPE_MAPPING_ID
) ?
'event_type_id' : 'id';
166 $query->where("r.{$valueField} IN (@selectedValues)")
167 ->param('selectedValues', $selectedValues);
170 $query->where(($this->id
== \CRM_Event_ActionMapping
::EVENT_TYPE_MAPPING_ID
) ?
"r.event_type_id IS NULL" : "r.id IS NULL");
173 $query->where('r.is_active = 1');
174 $query->where('r.is_template = 0');
176 // participant status criteria not to be implemented for additional recipients
178 if (!empty($selectedStatuses)) {
180 case RecipientBuilder
::PHASE_RELATION_FIRST
:
181 case RecipientBuilder
::PHASE_RELATION_REPEAT
:
182 $query->where("e.status_id IN (#selectedStatuses)")
183 ->param('selectedStatuses', $selectedStatuses);
192 * Determine whether a schedule based on this mapping should
193 * send to additional contacts.
195 * @param string $entityId Either an event ID/event type ID, or a set of event IDs/types separated
196 * by the separation character.
198 public function sendToAdditional($entityId): bool {
199 $selectedValues = (array) \CRM_Utils_Array
::explodePadded($entityId);
201 case self
::EVENT_TYPE_MAPPING_ID
:
203 $valueField = 'event_type_id';
204 $templateReminder = FALSE;
207 case self
::EVENT_NAME_MAPPING_ID
:
210 $templateReminder = FALSE;
213 case self
::EVENT_TPL_MAPPING_ID
:
216 $templateReminder = TRUE;
219 // Don't send to additional recipients if this event is deleted or a template.
220 $query = new \
CRM_Utils_SQL_Select('civicrm_event e');
223 ->where("e.is_template = 0")
224 ->where("e.is_active = 1");
225 if ($templateReminder) {
226 $query->join('r', 'INNER JOIN civicrm_event t ON e.template_title = t.template_title AND t.is_template = 1');
229 ->where("{$valueTable}.{$valueField} IN (@selectedValues)")
230 ->param('selectedValues', $selectedValues)
232 $dao = \CRM_Core_DAO
::executeQuery($sql);
233 return (bool) $dao->N
;