Merge pull request #16956 from jitendrapurohit/core-890
[civicrm-core.git] / CRM / Activity / Tokens.php
1 <?php
2
3 /*
4 +--------------------------------------------------------------------+
5 | Copyright CiviCRM LLC. All rights reserved. |
6 | |
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 |
10 +--------------------------------------------------------------------+
11 */
12
13 /**
14 * @package CRM
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
16 */
17
18 /**
19 * Class CRM_Member_Tokens
20 *
21 * Generate "activity.*" tokens.
22 *
23 * This TokenSubscriber was originally produced by refactoring the code from the
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.
29 *
30 * This has been enhanced to work with PDF/letter merge
31 */
32 class CRM_Activity_Tokens extends \Civi\Token\AbstractTokenSubscriber {
33
34 use CRM_Core_TokenTrait;
35
36 /**
37 * @return string
38 */
39 private function getEntityName(): string {
40 return 'activity';
41 }
42
43 /**
44 * @return string
45 */
46 private function getEntityTableName(): string {
47 return 'civicrm_activity';
48 }
49
50 /**
51 * @return string
52 */
53 private function getEntityContextSchema(): string {
54 return 'activityId';
55 }
56
57 /**
58 * Mapping from tokenName to api return field
59 * Use lists since we might need multiple fields
60 *
61 * @var array
62 */
63 private static $fieldMapping = [
64 'activity_id' => ['id'],
65 'activity_type' => ['activity_type_id'],
66 'status' => ['status_id'],
67 'campaign' => ['campaign_id'],
68 ];
69
70 /**
71 * @inheritDoc
72 */
73 public function alterActionScheduleQuery(\Civi\ActionSchedule\Event\MailingQueryEvent $e) {
74 if ($e->mapping->getEntity() !== $this->getEntityTableName()) {
75 return;
76 }
77
78 // The joint expression for activities needs some extra nuance to handle.
79 // Multiple revisions of the activity.
80 // Q: Could we simplify & move the extra AND clauses into `where(...)`?
81 $e->query->param('casEntityJoinExpr', 'e.id = reminder.entity_id AND e.is_current_revision = 1 AND e.is_deleted = 0');
82 }
83
84 /**
85 * @inheritDoc
86 */
87 public function prefetch(\Civi\Token\Event\TokenValueEvent $e) {
88 // Find all the entity IDs
89 $entityIds
90 = $e->getTokenProcessor()->getContextValues('actionSearchResult', 'entityID')
91 + $e->getTokenProcessor()->getContextValues($this->getEntityContextSchema());
92
93 if (!$entityIds) {
94 return NULL;
95 }
96
97 // Get data on all activities for basic and customfield tokens
98 $activities = civicrm_api3('Activity', 'get', [
99 'id' => ['IN' => $entityIds],
100 'options' => ['limit' => 0],
101 'return' => self::getReturnFields($this->activeTokens),
102 ]);
103 $prefetch['activity'] = $activities['values'];
104
105 // Store the activity types if needed
106 if (in_array('activity_type', $this->activeTokens)) {
107 $this->activityTypes = \CRM_Core_OptionGroup::values('activity_type');
108 }
109
110 // Store the activity statuses if needed
111 if (in_array('status', $this->activeTokens)) {
112 $this->activityStatuses = \CRM_Core_OptionGroup::values('activity_status');
113 }
114
115 // Store the campaigns if needed
116 if (in_array('campaign', $this->activeTokens)) {
117 $this->campaigns = \CRM_Campaign_BAO_Campaign::getCampaigns();
118 }
119
120 return $prefetch;
121 }
122
123 /**
124 * @inheritDoc
125 */
126 public function evaluateToken(\Civi\Token\TokenRow $row, $entity, $field, $prefetch = NULL) {
127 // maps token name to api field
128 $mapping = [
129 'activity_id' => 'id',
130 ];
131
132 // Get ActivityID either from actionSearchResult (for scheduled reminders) if exists
133 $activityId = $row->context['actionSearchResult']->entityID ?? $row->context[$this->getEntityContextSchema()];
134
135 $activity = (object) $prefetch['activity'][$activityId];
136
137 if (in_array($field, ['activity_date_time', 'created_date'])) {
138 $row->tokens($entity, $field, \CRM_Utils_Date::customFormat($activity->$field));
139 }
140 elseif (isset($mapping[$field]) and (isset($activity->{$mapping[$field]}))) {
141 $row->tokens($entity, $field, $activity->{$mapping[$field]});
142 }
143 elseif (in_array($field, ['activity_type'])) {
144 $row->tokens($entity, $field, $this->activityTypes[$activity->activity_type_id]);
145 }
146 elseif (in_array($field, ['status'])) {
147 $row->tokens($entity, $field, $this->activityStatuses[$activity->status_id]);
148 }
149 elseif (in_array($field, ['campaign'])) {
150 $row->tokens($entity, $field, $this->campaigns[$activity->campaign_id]);
151 }
152 elseif (in_array($field, ['case_id'])) {
153 // An activity can be linked to multiple cases so case_id is always an array.
154 // We just return the first case ID for the token.
155 $row->tokens($entity, $field, is_array($activity->case_id) ? reset($activity->case_id) : $activity->case_id);
156 }
157 elseif (array_key_exists($field, $this->customFieldTokens)) {
158 $row->tokens($entity, $field,
159 isset($activity->$field)
160 ? \CRM_Core_BAO_CustomField::displayValue($activity->$field, $field)
161 : ''
162 );
163 }
164 elseif (isset($activity->$field)) {
165 $row->tokens($entity, $field, $activity->$field);
166 }
167 }
168
169 /**
170 * Get the basic tokens provided.
171 *
172 * @return array token name => token label
173 */
174 protected function getBasicTokens() {
175 if (!isset($this->basicTokens)) {
176 $this->basicTokens = [
177 'activity_id' => ts('Activity ID'),
178 'activity_type' => ts('Activity Type'),
179 'subject' => ts('Activity Subject'),
180 'details' => ts('Activity Details'),
181 'activity_date_time' => ts('Activity Date-Time'),
182 'activity_type_id' => ts('Activity Type ID'),
183 'status' => ts('Activity Status'),
184 'status_id' => ts('Activity Status ID'),
185 'location' => ts('Activity Location'),
186 'created_date' => ts('Activity Creation Date'),
187 'duration' => ts('Activity Duration'),
188 'campaign' => ts('Activity Campaign'),
189 'campaign_id' => ts('Activity Campaign ID'),
190 ];
191 if (array_key_exists('CiviCase', CRM_Core_Component::getEnabledComponents())) {
192 $this->basicTokens['case_id'] = ts('Activity Case ID');
193 }
194 }
195 return $this->basicTokens;
196 }
197
198 }