4 +--------------------------------------------------------------------+
5 | Copyright CiviCRM LLC. All rights reserved. |
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 +--------------------------------------------------------------------+
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
19 * Class CRM_Member_Tokens
21 * Generate "activity.*" tokens.
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.
30 * This has been enhanced to work with PDF/letter merge
32 class CRM_Activity_Tokens
extends \Civi\Token\AbstractTokenSubscriber
{
34 use CRM_Core_TokenTrait
;
39 private function getEntityName(): string {
46 private function getEntityTableName(): string {
47 return 'civicrm_activity';
53 private function getEntityContextSchema(): string {
58 * Mapping from tokenName to api return field
59 * Using arrays allows more complex tokens to be handled that require more than one API field.
60 * For example, an address token might want ['street_address', 'city', 'postal_code']
64 private static $fieldMapping = [
65 'activity_id' => ['id'],
66 'activity_type' => ['activity_type_id'],
67 'status' => ['status_id'],
68 'campaign' => ['campaign_id'],
74 public function alterActionScheduleQuery(\Civi\ActionSchedule\Event\MailingQueryEvent
$e) {
75 if ($e->mapping
->getEntity() !== $this->getEntityTableName()) {
79 // The joint expression for activities needs some extra nuance to handle.
80 // Multiple revisions of the activity.
81 // Q: Could we simplify & move the extra AND clauses into `where(...)`?
82 $e->query
->param('casEntityJoinExpr', 'e.id = reminder.entity_id AND e.is_current_revision = 1 AND e.is_deleted = 0');
88 public function prefetch(\Civi\Token\Event\TokenValueEvent
$e) {
89 // Find all the entity IDs
91 = $e->getTokenProcessor()->getContextValues('actionSearchResult', 'entityID')
92 +
$e->getTokenProcessor()->getContextValues($this->getEntityContextSchema());
98 // Get data on all activities for basic and customfield tokens
99 $activities = civicrm_api3('Activity', 'get', [
100 'id' => ['IN' => $entityIds],
101 'options' => ['limit' => 0],
102 'return' => self
::getReturnFields($this->activeTokens
),
104 $prefetch['activity'] = $activities['values'];
106 // Store the activity types if needed
107 if (in_array('activity_type', $this->activeTokens
)) {
108 $this->activityTypes
= \CRM_Core_OptionGroup
::values('activity_type');
111 // Store the activity statuses if needed
112 if (in_array('status', $this->activeTokens
)) {
113 $this->activityStatuses
= \CRM_Core_OptionGroup
::values('activity_status');
116 // Store the campaigns if needed
117 if (in_array('campaign', $this->activeTokens
)) {
118 $this->campaigns
= \CRM_Campaign_BAO_Campaign
::getCampaigns();
127 public function evaluateToken(\Civi\Token\TokenRow
$row, $entity, $field, $prefetch = NULL) {
128 // maps token name to api field
130 'activity_id' => 'id',
133 // Get ActivityID either from actionSearchResult (for scheduled reminders) if exists
134 $activityId = $row->context
['actionSearchResult']->entityID ??
$row->context
[$this->getEntityContextSchema()];
136 $activity = $prefetch['activity'][$activityId];
138 if (in_array($field, ['activity_date_time', 'created_date', 'modified_date'])) {
139 $row->tokens($entity, $field, \CRM_Utils_Date
::customFormat($activity[$field]));
141 elseif (isset($mapping[$field]) and (isset($activity[$mapping[$field]]))) {
142 $row->tokens($entity, $field, $activity[$mapping[$field]]);
144 elseif (in_array($field, ['activity_type'])) {
145 $row->tokens($entity, $field, $this->activityTypes
[$activity['activity_type_id']]);
147 elseif (in_array($field, ['status'])) {
148 $row->tokens($entity, $field, $this->activityStatuses
[$activity['status_id']]);
150 elseif (in_array($field, ['campaign'])) {
151 $row->tokens($entity, $field, $this->campaigns
[$activity['campaign_id']]);
153 elseif (in_array($field, ['case_id'])) {
154 // An activity can be linked to multiple cases so case_id is always an array.
155 // We just return the first case ID for the token.
156 $row->tokens($entity, $field, is_array($activity['case_id']) ?
reset($activity['case_id']) : $activity['case_id']);
158 elseif (array_key_exists($field, $this->customFieldTokens
)) {
159 $row->tokens($entity, $field,
160 isset($activity[$field])
161 ? \CRM_Core_BAO_CustomField
::displayValue($activity[$field], $field)
165 elseif (isset($activity[$field])) {
166 $row->tokens($entity, $field, $activity[$field]);
171 * Get the basic tokens provided.
173 * @return array token name => token label
175 protected function getBasicTokens() {
176 if (!isset($this->basicTokens
)) {
177 $this->basicTokens
= [
178 'activity_id' => ts('Activity ID'),
179 'activity_type' => ts('Activity Type'),
180 'subject' => ts('Activity Subject'),
181 'details' => ts('Activity Details'),
182 'activity_date_time' => ts('Activity Date-Time'),
183 'created_date' => ts('Activity Created Date'),
184 'modified_date' => ts('Activity Modified Date'),
185 'activity_type_id' => ts('Activity Type ID'),
186 'status' => ts('Activity Status'),
187 'status_id' => ts('Activity Status ID'),
188 'location' => ts('Activity Location'),
189 'duration' => ts('Activity Duration'),
190 'campaign' => ts('Activity Campaign'),
191 'campaign_id' => ts('Activity Campaign ID'),
193 if (array_key_exists('CiviCase', CRM_Core_Component
::getEnabledComponents())) {
194 $this->basicTokens
['case_id'] = ts('Activity Case ID');
197 return $this->basicTokens
;