dev/core#1592 fix regression on relation active period
[civicrm-core.git] / CRM / Activity / Tokens.php
CommitLineData
46f5566c
TO
1<?php
2
3/*
4 +--------------------------------------------------------------------+
bc77d7c0 5 | Copyright CiviCRM LLC. All rights reserved. |
46f5566c 6 | |
bc77d7c0
TO
7 | This work is published under the GNU AGPLv3 license with some |
8 | permitted exceptions and without any warranty. For full license |
9 | and copyright information, see https://civicrm.org/licensing |
46f5566c
TO
10 +--------------------------------------------------------------------+
11 */
12
7808aae6
SB
13/**
14 * @package CRM
ca5cec67 15 * @copyright CiviCRM LLC https://civicrm.org/licensing
7808aae6
SB
16 */
17
46f5566c
TO
18/**
19 * Class CRM_Member_Tokens
20 *
21 * Generate "activity.*" tokens.
22 *
da9977bd 23 * This TokenSubscriber was originally produced by refactoring the code from the
46f5566c
TO
24 * scheduled-reminder system with the goal of making that system
25 * more flexible. The current implementation is still coupled to
26 * scheduled-reminders. It would be good to figure out a more generic
27 * implementation which is not tied to scheduled reminders, although
28 * that is outside the current scope.
da9977bd
AS
29 *
30 * This has been enhanced to work with PDF/letter merge
46f5566c
TO
31 */
32class CRM_Activity_Tokens extends \Civi\Token\AbstractTokenSubscriber {
33
da9977bd
AS
34 private $basicTokens;
35 private $customFieldTokens;
36
37 /**
38 * Mapping from tokenName to api return field
39 * Use lists since we might need multiple fields
40 *
41 * @var array
42 */
43 private static $fieldMapping = [
44 'activity_id' => ['id'],
45 'activity_type' => ['activity_type_id'],
46 'status' => ['status_id'],
47 'campaign' => ['campaign_id'],
48 ];
49
8246bca4 50 /**
51 * CRM_Activity_Tokens constructor.
52 */
46f5566c 53 public function __construct() {
4e9b6a62 54 parent::__construct('activity', array_merge(
86420016 55 $this->getBasicTokens(),
56 $this->getCustomFieldTokens()
46f5566c
TO
57 ));
58 }
59
70599df6 60 /**
298795cd 61 * @inheritDoc
70599df6 62 */
46f5566c 63 public function checkActive(\Civi\Token\TokenProcessor $processor) {
da9977bd
AS
64 return in_array('activityId', $processor->context['schema']) ||
65 (!empty($processor->context['actionMapping'])
66 && $processor->context['actionMapping']->getEntity() === 'civicrm_activity');
67 }
68
69 /**
70 * @inheritDoc
71 */
72 public function getActiveTokens(\Civi\Token\Event\TokenValueEvent $e) {
73 $messageTokens = $e->getTokenProcessor()->getMessageTokens();
74 if (!isset($messageTokens[$this->entity])) {
75 return NULL;
76 }
77
78 $activeTokens = [];
79 // if message token contains '_\d+_', then treat as '_N_'
80 foreach ($messageTokens[$this->entity] as $msgToken) {
81 if (array_key_exists($msgToken, $this->tokenNames)) {
82 $activeTokens[] = $msgToken;
83 }
84 else {
85 $altToken = preg_replace('/_\d+_/', '_N_', $msgToken);
86 if (array_key_exists($altToken, $this->tokenNames)) {
87 $activeTokens[] = $msgToken;
88 }
89 }
90 }
91 return array_unique($activeTokens);
46f5566c
TO
92 }
93
298795cd
TO
94 /**
95 * @inheritDoc
96 */
f9ec2da6
TO
97 public function alterActionScheduleQuery(\Civi\ActionSchedule\Event\MailingQueryEvent $e) {
98 if ($e->mapping->getEntity() !== 'civicrm_activity') {
99 return;
100 }
101
7808aae6
SB
102 // The joint expression for activities needs some extra nuance to handle.
103 // Multiple revisions of the activity.
104 // Q: Could we simplify & move the extra AND clauses into `where(...)`?
f9ec2da6 105 $e->query->param('casEntityJoinExpr', 'e.id = reminder.entity_id AND e.is_current_revision = 1 AND e.is_deleted = 0');
da9977bd 106 }
f9ec2da6 107
da9977bd
AS
108 /**
109 * Find the fields that we need to get to construct the tokens requested.
110 * @param array $tokens list of tokens
111 * @return array list of fields needed to generate those tokens
112 */
113 public function getReturnFields($tokens) {
114 // Make sure we always return something
115 $fields = ['id'];
f9ec2da6 116
da9977bd
AS
117 foreach (array_intersect($tokens,
118 array_merge(array_keys(self::getBasicTokens()), array_keys(self::getCustomFieldTokens()))
119 ) as $token) {
120 if (isset(self::$fieldMapping[$token])) {
121 $fields = array_merge($fields, self::$fieldMapping[$token]);
122 }
123 else {
124 $fields[] = $token;
125 }
126 }
127 return array_unique($fields);
128 }
f9ec2da6 129
da9977bd
AS
130 /**
131 * @inheritDoc
132 */
133 public function prefetch(\Civi\Token\Event\TokenValueEvent $e) {
134 // Find all the activity IDs
135 $activityIds
136 = $e->getTokenProcessor()->getContextValues('actionSearchResult', 'entityID')
137 + $e->getTokenProcessor()->getContextValues('activityId');
138
139 if (!$activityIds) {
140 return;
141 }
142
143 // Get data on all activities for basic and customfield tokens
144 $activities = civicrm_api3('Activity', 'get', [
145 'id' => ['IN' => $activityIds],
146 'options' => ['limit' => 0],
147 'return' => self::getReturnFields($this->activeTokens),
148 ]);
149 $prefetch['activity'] = $activities['values'];
150
151 // Store the activity types if needed
152 if (in_array('activity_type', $this->activeTokens)) {
153 $this->activityTypes = \CRM_Core_OptionGroup::values('activity_type');
154 }
155
156 // Store the activity statuses if needed
157 if (in_array('status', $this->activeTokens)) {
158 $this->activityStatuses = \CRM_Core_OptionGroup::values('activity_status');
159 }
160
161 // Store the campaigns if needed
162 if (in_array('campaign', $this->activeTokens)) {
163 $this->campaigns = \CRM_Campaign_BAO_Campaign::getCampaigns();
f9ec2da6 164 }
da9977bd
AS
165
166 return $prefetch;
f9ec2da6
TO
167 }
168
46f5566c 169 /**
298795cd 170 * @inheritDoc
46f5566c
TO
171 */
172 public function evaluateToken(\Civi\Token\TokenRow $row, $entity, $field, $prefetch = NULL) {
da9977bd
AS
173 // maps token name to api field
174 $mapping = [
175 'activity_id' => 'id',
176 ];
177
178 // Get ActivityID either from actionSearchResult (for scheduled reminders) if exists
179 $activityId = isset($row->context['actionSearchResult']->entityID)
180 ? $row->context['actionSearchResult']->entityID
181 : $row->context['activityId'];
46f5566c 182
da9977bd
AS
183 $activity = (object) $prefetch['activity'][$activityId];
184
185 if (in_array($field, ['activity_date_time', 'created_date'])) {
186 $row->tokens($entity, $field, \CRM_Utils_Date::customFormat($activity->$field));
187 }
188 elseif (isset($mapping[$field]) and (isset($activity->{$mapping[$field]}))) {
189 $row->tokens($entity, $field, $activity->{$mapping[$field]});
46f5566c 190 }
da9977bd
AS
191 elseif (in_array($field, ['activity_type'])) {
192 $row->tokens($entity, $field, $this->activityTypes[$activity->activity_type_id]);
46f5566c 193 }
da9977bd
AS
194 elseif (in_array($field, ['status'])) {
195 $row->tokens($entity, $field, $this->activityStatuses[$activity->status_id]);
4e9b6a62 196 }
da9977bd
AS
197 elseif (in_array($field, ['campaign'])) {
198 $row->tokens($entity, $field, $this->campaigns[$activity->campaign_id]);
199 }
28f7a9b1
MW
200 elseif (in_array($field, ['case_id'])) {
201 // An activity can be linked to multiple cases so case_id is always an array.
202 // We just return the first case ID for the token.
203 $row->tokens($entity, $field, is_array($activity->case_id) ? reset($activity->case_id) : $activity->case_id);
204 }
da9977bd
AS
205 elseif (array_key_exists($field, $this->customFieldTokens)) {
206 $row->tokens($entity, $field,
207 isset($activity->$field)
208 ? \CRM_Core_BAO_CustomField::displayValue($activity->$field, $field)
209 : ''
210 );
211 }
212 elseif (isset($activity->$field)) {
213 $row->tokens($entity, $field, $activity->$field);
46f5566c
TO
214 }
215 }
216
86420016 217 /**
218 * Get the basic tokens provided.
219 *
220 * @return array token name => token label
221 */
222 protected function getBasicTokens() {
da9977bd
AS
223 if (!isset($this->basicTokens)) {
224 $this->basicTokens = [
225 'activity_id' => ts('Activity ID'),
226 'activity_type' => ts('Activity Type'),
227 'subject' => ts('Activity Subject'),
228 'details' => ts('Activity Details'),
229 'activity_date_time' => ts('Activity Date-Time'),
230 'activity_type_id' => ts('Activity Type ID'),
231 'status' => ts('Activity Status'),
232 'status_id' => ts('Activity Status ID'),
233 'location' => ts('Activity Location'),
234 'created_date' => ts('Activity Creation Date'),
235 'duration' => ts('Activity Duration'),
236 'campaign' => ts('Activity Campaign'),
237 'campaign_id' => ts('Activity Campaign ID'),
238 ];
239 if (array_key_exists('CiviCase', CRM_Core_Component::getEnabledComponents())) {
240 $this->basicTokens['case_id'] = ts('Activity Case ID');
241 }
242 }
243 return $this->basicTokens;
86420016 244 }
245
246 /**
247 * Get the tokens for custom fields
248 * @return array token name => token label
249 */
250 protected function getCustomFieldTokens() {
da9977bd
AS
251 if (!isset($this->customFieldTokens)) {
252 $this->customFieldTokens = \CRM_Utils_Token::getCustomFieldTokens('Activity');
253 }
254 return $this->customFieldTokens;
86420016 255 }
256
46f5566c 257}