Merge pull request #21652 from eileenmcnaughton/cont_render_more
[civicrm-core.git] / tests / phpunit / CRM / Utils / TokenConsistencyTest.php
CommitLineData
d0ce76fd
EM
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
0f4031da 12use Civi\Token\TokenProcessor;
f399fbd8
EM
13use Civi\Api4\LocBlock;
14use Civi\Api4\Email;
15use Civi\Api4\Phone;
16use Civi\Api4\Address;
0f4031da 17
d0ce76fd
EM
18/**
19 * CRM_Utils_TokenConsistencyTest
20 *
21 * Class for ensuring tokens have internal consistency.
22 *
23 * @group Tokens
24 *
25 * @group headless
26 */
27class CRM_Utils_TokenConsistencyTest extends CiviUnitTestCase {
28
29 use CRMTraits_Custom_CustomDataTrait;
30
31 /**
32 * Created case.
33 *
34 * @var array
35 */
36 protected $case;
37
0f4031da
EM
38 /**
39 * Recurring contribution.
40 *
41 * @var array
42 */
43 protected $contributionRecur;
44
d0ce76fd
EM
45 /**
46 * Post test cleanup.
47 *
48 * @throws \API_Exception
49 * @throws \CRM_Core_Exception
50 */
51 public function tearDown(): void {
d568dbe0 52 $this->quickCleanup(['civicrm_case', 'civicrm_case_type'], TRUE);
d0ce76fd
EM
53 parent::tearDown();
54 }
55
56 /**
57 * Test that case tokens are consistently rendered.
58 *
d0ce76fd
EM
59 * @throws \CiviCRM_API3_Exception
60 */
61 public function testCaseTokenConsistency(): void {
62 $this->createLoggedInUser();
63 CRM_Core_BAO_ConfigSetting::enableComponent('CiviCase');
64 $this->createCustomGroupWithFieldOfType(['extends' => 'Case']);
65 $tokens = CRM_Core_SelectValues::caseTokens();
66 $this->assertEquals($this->getCaseTokens(), $tokens);
67 $caseID = $this->getCaseID();
78ffc4d7
EM
68 $tokenString = implode("\n", array_keys($this->getCaseTokens()));
69 $tokenHtml = CRM_Utils_Token::replaceCaseTokens($caseID, $tokenString, ['case' => $this->getCaseTokenKeys()]);
d0ce76fd
EM
70 $this->assertEquals($this->getExpectedCaseTokenOutput(), $tokenHtml);
71 // Now do the same without passing in 'knownTokens'
78ffc4d7 72 $tokenHtml = CRM_Utils_Token::replaceCaseTokens($caseID, $tokenString);
d0ce76fd 73 $this->assertEquals($this->getExpectedCaseTokenOutput(), $tokenHtml);
2f5c0408
EM
74
75 // And check our deprecated tokens still work.
76 $tokenHtml = CRM_Utils_Token::replaceCaseTokens($caseID, '{case.case_type_id} {case.status_id}');
77 $this->assertEquals('Housing Support Ongoing', $tokenHtml);
78ffc4d7
EM
78
79 $additionalTokensFromProcessor = [
80 '{case.case_type_id}' => 'Case Type ID',
81 '{case.status_id}' => 'Case Status',
82 '{case.case_type_id:name}' => 'Machine name: Case Type',
83 '{case.status_id:name}' => 'Machine name: Case Status',
84 ];
85 $expectedTokens = array_merge($this->getCaseTokens(), $additionalTokensFromProcessor);
86
87 $tokenProcessor = new TokenProcessor(\Civi::dispatcher(), [
88 'controller' => __CLASS__,
89 'smarty' => FALSE,
90 'schema' => ['caseId'],
91 ]);
3c78698e 92 $this->assertEquals(array_merge($expectedTokens, $this->getDomainTokens()), $tokenProcessor->listTokens());
78ffc4d7
EM
93 $tokenProcessor->addRow([
94 'caseId' => $this->getCaseID(),
95 ]);
96 $tokenProcessor->addMessage('html', $tokenString, 'text/plain');
97
98 $tokenProcessor->evaluate();
99 foreach ($tokenProcessor->getRows() as $row) {
100 $text = $row->render('html');
101 }
102 $this->assertEquals($this->getExpectedCaseTokenOutput(), $text);
d0ce76fd
EM
103 }
104
105 /**
106 * Get expected output from token parsing.
107 *
108 * @return string
109 */
110 protected function getExpectedCaseTokenOutput(): string {
111 return '1
112Housing Support
113Case Subject
114July 23rd, 2021
115July 26th, 2021
116case details
117Ongoing
118No
78ffc4d7
EM
119' . CRM_Utils_Date::customFormat($this->case['created_date']) . '
120' . CRM_Utils_Date::customFormat($this->case['modified_date']) . '
d0ce76fd
EM
121';
122 }
123
124 /**
125 * @return int
126 */
127 protected function getContactID(): int {
128 if (!isset($this->ids['Contact'][0])) {
129 $this->ids['Contact'][0] = $this->individualCreate();
130 }
131 return $this->ids['Contact'][0];
132 }
133
134 /**
135 * Get the keys for the case tokens.
136 *
137 * @return array
138 */
139 public function getCaseTokenKeys(): array {
140 $return = [];
141 foreach (array_keys($this->getCaseTokens()) as $key) {
142 $return[] = substr($key, 6, -1);
143 }
144 return $return;
145 }
146
147 /**
148 * Get declared tokens.
149 *
150 * @return string[]
151 */
152 public function getCaseTokens(): array {
153 return [
154 '{case.id}' => 'Case ID',
2f5c0408 155 '{case.case_type_id:label}' => 'Case Type',
d0ce76fd
EM
156 '{case.subject}' => 'Case Subject',
157 '{case.start_date}' => 'Case Start Date',
158 '{case.end_date}' => 'Case End Date',
159 '{case.details}' => 'Details',
2f5c0408 160 '{case.status_id:label}' => 'Case Status',
78ffc4d7 161 '{case.is_deleted:label}' => 'Case is in the Trash',
d0ce76fd
EM
162 '{case.created_date}' => 'Created Date',
163 '{case.modified_date}' => 'Modified Date',
164 '{case.custom_1}' => 'Enter text here :: Group with field text',
165 ];
166 }
167
168 /**
169 * Get case ID.
170 *
171 * @return int
172 */
173 protected function getCaseID(): int {
174 if (!isset($this->case)) {
a0fb3068 175 $case_id = $this->callAPISuccess('Case', 'create', [
d0ce76fd
EM
176 'case_type_id' => 'housing_support',
177 'activity_subject' => 'Case Subject',
178 'client_id' => $this->getContactID(),
179 'status_id' => 1,
180 'subject' => 'Case Subject',
181 'start_date' => '2021-07-23 15:39:20',
a0fb3068 182 // Note end_date is inconsistent with status Ongoing but for the
183 // purposes of testing tokens is ok. Creating it with status Resolved
184 // then ignores our known fixed end date.
d0ce76fd
EM
185 'end_date' => '2021-07-26 18:07:20',
186 'medium_id' => 2,
187 'details' => 'case details',
188 'activity_details' => 'blah blah',
189 'sequential' => 1,
a0fb3068 190 ])['id'];
191 // Need to retrieve the case again because modified date might be updated a
192 // split-second later than the original return value because of activity
193 // triggers when the timeline is populated. The returned array from create
194 // is determined before that happens.
195 $this->case = $this->callAPISuccess('Case', 'getsingle', ['id' => $case_id]);
d0ce76fd
EM
196 }
197 return $this->case['id'];
198 }
199
0f4031da
EM
200 /**
201 * Test that contribution recur tokens are consistently rendered.
202 */
203 public function testContributionRecurTokenConsistency(): void {
204 $this->createLoggedInUser();
205 $tokenProcessor = new TokenProcessor(\Civi::dispatcher(), [
206 'controller' => __CLASS__,
207 'smarty' => FALSE,
208 'schema' => ['contribution_recurId'],
209 ]);
3c78698e 210 $this->assertEquals(array_merge($this->getContributionRecurTokens(), $this->getDomainTokens()), $tokenProcessor->listTokens());
0f4031da
EM
211 $tokenString = implode("\n", array_keys($this->getContributionRecurTokens()));
212
213 $tokenProcessor->addMessage('html', $tokenString, 'text/plain');
214 $tokenProcessor->addRow(['contribution_recurId' => $this->getContributionRecurID()]);
215 $tokenProcessor->evaluate();
216 $this->assertEquals($this->getExpectedContributionRecurTokenOutPut(), $tokenProcessor->getRow(0)->render('html'));
217 }
218
219 /**
220 * Get the contribution recur tokens keyed by the token.
221 *
222 * e.g {contribution_recur.id}
223 *
224 * @return array
225 */
226 protected function getContributionRecurTokens(): array {
227 $return = [];
228 foreach ($this->getContributionRecurTokensByField() as $key => $value) {
229 $return['{contribution_recur.' . $key . '}'] = $value;
230 }
231 return $return;
232 }
233
234 protected function getContributionRecurTokensByField(): array {
235 return [
236 'id' => 'Recurring Contribution ID',
237 'amount' => 'Amount',
238 'currency' => 'Currency',
239 'frequency_unit' => 'Frequency Unit',
240 'frequency_interval' => 'Interval (number of units)',
241 'installments' => 'Number of Installments',
242 'start_date' => 'Start Date',
243 'create_date' => 'Created Date',
244 'modified_date' => 'Modified Date',
245 'cancel_date' => 'Cancel Date',
246 'cancel_reason' => 'Cancellation Reason',
247 'end_date' => 'Recurring Contribution End Date',
248 'processor_id' => 'Processor ID',
249 'payment_token_id' => 'Payment Token ID',
250 'trxn_id' => 'Transaction ID',
251 'invoice_id' => 'Invoice ID',
252 'contribution_status_id' => 'Status',
97ca72e4 253 'is_test:label' => 'Test',
0f4031da
EM
254 'cycle_day' => 'Cycle Day',
255 'next_sched_contribution_date' => 'Next Scheduled Contribution Date',
256 'failure_count' => 'Number of Failures',
257 'failure_retry_date' => 'Retry Failed Attempt Date',
97ca72e4 258 'auto_renew:label' => 'Auto Renew',
0f4031da
EM
259 'payment_processor_id' => 'Payment Processor ID',
260 'financial_type_id' => 'Financial Type ID',
261 'payment_instrument_id' => 'Payment Method',
97ca72e4 262 'is_email_receipt:label' => 'Send email Receipt?',
0f4031da
EM
263 'frequency_unit:label' => 'Frequency Unit',
264 'frequency_unit:name' => 'Machine name: Frequency Unit',
265 'contribution_status_id:label' => 'Status',
266 'contribution_status_id:name' => 'Machine name: Status',
267 'payment_processor_id:label' => 'Payment Processor',
268 'payment_processor_id:name' => 'Machine name: Payment Processor',
269 'financial_type_id:label' => 'Financial Type',
270 'financial_type_id:name' => 'Machine name: Financial Type',
271 'payment_instrument_id:label' => 'Payment Method',
272 'payment_instrument_id:name' => 'Machine name: Payment Method',
273 ];
274 }
275
276 /**
277 * Get contributionRecur ID.
278 *
279 * @return int
280 */
281 protected function getContributionRecurID(): int {
282 if (!isset($this->contributionRecur)) {
283 $paymentProcessorID = $this->processorCreate();
284 $this->contributionRecur = $this->callAPISuccess('ContributionRecur', 'create', [
285 'contact_id' => $this->getContactID(),
286 'status_id' => 1,
287 'is_email_receipt' => 1,
288 'start_date' => '2021-07-23 15:39:20',
289 'end_date' => '2021-07-26 18:07:20',
290 'cancel_date' => '2021-08-19 09:12:45',
34795e7a 291 'next_sched_contribution_date' => '2021-09-08',
0f4031da
EM
292 'cancel_reason' => 'Because',
293 'amount' => 5990.99,
294 'currency' => 'EUR',
295 'frequency_unit' => 'year',
296 'frequency_interval' => 2,
297 'installments' => 24,
298 'payment_instrument_id' => 'Check',
299 'financial_type_id' => 'Member dues',
300 'processor_id' => 'abc',
301 'payment_processor_id' => $paymentProcessorID,
302 'trxn_id' => 123,
303 'invoice_id' => 'inv123',
304 'sequential' => 1,
305 'failure_retry_date' => '2020-01-03',
306 'auto_renew' => 1,
307 'cycle_day' => '15',
308 'is_test' => TRUE,
309 'payment_token_id' => $this->callAPISuccess('PaymentToken', 'create', [
310 'contact_id' => $this->getContactID(),
311 'token' => 456,
312 'payment_processor_id' => $paymentProcessorID,
313 ])['id'],
314 ])['values'][0];
315 }
316 return $this->contributionRecur['id'];
317 }
318
319 /**
320 * Get rendered output for contribution tokens.
321 *
322 * @return string
323 */
324 protected function getExpectedContributionRecurTokenOutPut(): string {
325 return $this->getContributionRecurID() . '
326€ 5,990.99
327EUR
328year
3292
33024
331July 23rd, 2021 3:39 PM
332' . CRM_Utils_Date::customFormat($this->contributionRecur['create_date']) . '
333' . CRM_Utils_Date::customFormat($this->contributionRecur['modified_date']) . '
334August 19th, 2021 9:12 AM
335Because
336July 26th, 2021 6:07 PM
337abc
3381
339123
340inv123
3412
97ca72e4 342Yes
0f4031da 34315
34795e7a 344September 8th, 2021
0f4031da 3450
34795e7a 346January 3rd, 2020
97ca72e4 347Yes
0f4031da
EM
3481
3492
3504
97ca72e4 351Yes
0f4031da
EM
352year
353year
354Pending Label**
355Pending
97ca72e4
EM
356Dummy (test)
357Dummy (test)
0f4031da
EM
358Member Dues
359Member Dues
360Check
361Check';
362 }
363
d41a5d53
EM
364 /**
365 * Test that membership tokens are consistently rendered.
366 *
367 * @throws \API_Exception
368 */
369 public function testMembershipTokenConsistency(): void {
370 $this->createLoggedInUser();
371 $this->restoreMembershipTypes();
372 $this->createCustomGroupWithFieldOfType(['extends' => 'Membership']);
373 $tokens = CRM_Core_SelectValues::membershipTokens();
d568dbe0
EM
374 $expectedTokens = $this->getMembershipTokens();
375 $this->assertEquals($expectedTokens, $tokens);
d41a5d53
EM
376 $newStyleTokens = "\n{membership.status_id:label}\n{membership.membership_type_id:label}\n";
377 $tokenString = $newStyleTokens . implode("\n", array_keys($this->getMembershipTokens()));
b024d6a1 378
d41a5d53
EM
379 $memberships = CRM_Utils_Token::getMembershipTokenDetails([$this->getMembershipID()]);
380 $messageToken = CRM_Utils_Token::getTokens($tokenString);
381 $tokenHtml = CRM_Utils_Token::replaceEntityTokens('membership', $memberships[$this->getMembershipID()], $tokenString, $messageToken);
382 $this->assertEquals($this->getExpectedMembershipTokenOutput(), $tokenHtml);
dd2f879a 383
b024d6a1
EM
384 // Custom fields work in the processor so test it....
385 $tokenString .= "\n{membership." . $this->getCustomFieldName('text') . '}';
dd2f879a
EM
386 // Now compare with scheduled reminder
387 $mut = new CiviMailUtils($this);
388 CRM_Utils_Time::setTime('2007-01-22 15:00:00');
389 $this->callAPISuccess('action_schedule', 'create', [
390 'title' => 'job',
391 'subject' => 'job',
392 'entity_value' => 1,
393 'mapping_id' => 4,
394 'start_action_date' => 'membership_join_date',
395 'start_action_offset' => 1,
396 'start_action_condition' => 'after',
397 'start_action_unit' => 'day',
398 'body_html' => $tokenString,
399 ]);
400 $this->callAPISuccess('job', 'send_reminder', []);
d568dbe0
EM
401 $expected = $this->getExpectedMembershipTokenOutput();
402 // Unlike the legacy method custom fields are resolved by the processor.
403 $expected .= "\nmy field";
404 $mut->checkMailLog([$expected]);
405
406 $tokenProcessor = new TokenProcessor(\Civi::dispatcher(), [
407 'controller' => __CLASS__,
408 'smarty' => FALSE,
409 'schema' => ['membershipId'],
410 ]);
411 $tokens = $tokenProcessor->listTokens();
412 // Add in custom tokens as token processor supports these.
413 $expectedTokens['{membership.custom_1}'] = 'Enter text here :: Group with field text';
3c78698e 414 $this->assertEquals(array_merge($expectedTokens, $this->getDomainTokens()), $tokens);
d568dbe0
EM
415 $tokenProcessor->addMessage('html', $tokenString, 'text/plain');
416 $tokenProcessor->addRow(['membershipId' => $this->getMembershipID()]);
417 $tokenProcessor->evaluate();
418 $this->assertEquals($expected, $tokenProcessor->getRow(0)->render('html'));
419
d41a5d53
EM
420 }
421
422 /**
423 * Get declared membership tokens.
424 *
425 * @return string[]
426 */
427 public function getMembershipTokens(): array {
428 return [
429 '{membership.id}' => 'Membership ID',
eac0a5bf
EM
430 '{membership.status_id:label}' => 'Membership Status',
431 '{membership.membership_type_id:label}' => 'Membership Type',
d41a5d53
EM
432 '{membership.start_date}' => 'Membership Start Date',
433 '{membership.join_date}' => 'Membership Join Date',
434 '{membership.end_date}' => 'Membership End Date',
435 '{membership.fee}' => 'Membership Fee',
436 ];
437 }
438
439 /**
440 * Get case ID.
441 *
442 * @return int
443 */
444 protected function getMembershipID(): int {
445 if (!isset($this->ids['Membership'][0])) {
b024d6a1
EM
446 $this->ids['Membership'][0] = $this->contactMembershipCreate([
447 'contact_id' => $this->getContactID(),
448 $this->getCustomFieldName('text') => 'my field',
449 ]);
d41a5d53
EM
450 }
451 return $this->ids['Membership'][0];
452 }
453
f399fbd8
EM
454 /**
455 * Get expected output from token parsing.
456 *
457 * @return string
458 */
459 protected function getExpectedEventTokenOutput(): string {
460 return '
4611
462Annual CiviCRM meet
873bfeb5
EM
463October 21st, 2008
464October 23rd, 2008
f399fbd8
EM
465Conference
466If you have any CiviCRM related issues or want to track where CiviCRM is heading, Sign up now
467event@example.com
468456 789
469event description
47015 Walton St
471Emerald City, Maine 90210
472
473$ 50.00
873bfeb5
EM
474' . CRM_Utils_System::url('civicrm/event/info', NULL, TRUE) . '&reset=1&id=1
475' . CRM_Utils_System::url('civicrm/event/register', NULL, TRUE) . '&reset=1&id=1
f399fbd8
EM
476
477my field';
478 }
479
d41a5d53
EM
480 /**
481 * Get expected output from token parsing.
482 *
483 * @return string
484 */
485 protected function getExpectedMembershipTokenOutput(): string {
486 return '
487Expired
488General
4891
490Expired
491General
492January 21st, 2007
493January 21st, 2007
494December 21st, 2007
495100.00';
496 }
497
1ed50dc6
EM
498 /**
499 * Test that membership tokens are consistently rendered.
500 *
501 * @throws \API_Exception
502 */
503 public function testParticipantTokenConsistency(): void {
504 $this->createLoggedInUser();
505 $this->createCustomGroupWithFieldOfType(['extends' => 'Participant']);
506 $tokens = CRM_Core_SelectValues::participantTokens();
507 $this->assertEquals($this->getParticipantTokens(), $tokens);
508 }
509
510 /**
3c78698e 511 * Get declared participant tokens.
1ed50dc6
EM
512 *
513 * @return string[]
514 */
515 public function getParticipantTokens(): array {
516 return [
b7472bd6
EM
517 '{participant.status_id}' => 'Status ID',
518 '{participant.role_id}' => 'Participant Role (ID)',
519 '{participant.register_date}' => 'Register date',
520 '{participant.source}' => 'Participant Source',
521 '{participant.fee_level}' => 'Fee level',
522 '{participant.fee_amount}' => 'Fee Amount',
523 '{participant.registered_by_id}' => 'Registered By Participant ID',
1ed50dc6 524 '{participant.transferred_to_contact_id}' => 'Transferred to Contact ID',
b7472bd6 525 '{participant.role_id:label}' => 'Participant Role (label)',
1ed50dc6 526 '{participant.fee_label}' => 'Fee Label',
1ed50dc6
EM
527 '{participant.' . $this->getCustomFieldName('text') . '}' => 'Enter text here :: Group with field text',
528 ];
529 }
530
3c78698e
EM
531 /**
532 * Test that domain tokens are consistently rendered.
533 */
534 public function testDomainTokenConsistency(): void {
535 $tokens = CRM_Core_SelectValues::domainTokens();
536 $this->assertEquals($this->getDomainTokens(), $tokens);
537 $tokenProcessor = new TokenProcessor(\Civi::dispatcher(), [
538 'controller' => __CLASS__,
539 'smarty' => FALSE,
540 ]);
541 $tokens['{domain.id}'] = 'Domain ID';
542 $tokens['{domain.description}'] = 'Domain Description';
dfe53edd 543 $tokens['{domain.now}'] = 'Current time/date';
3c78698e
EM
544 $this->assertEquals($tokens, $tokenProcessor->listTokens());
545 }
546
defba8ff
EM
547 /**
548 * @throws \API_Exception
549 * @throws \CRM_Core_Exception
550 */
551 public function testDomainNow(): void {
552 putenv('TIME_FUNC=frozen');
5e62af3d 553 CRM_Utils_Time::setTime('2021-09-18 23:58:00');
44dd64f0
EM
554 $modifiers = [
555 'shortdate' => '09/18/2021',
f85e1a4b 556 '%B %Y' => 'September 2021',
44dd64f0
EM
557 ];
558 foreach ($modifiers as $filter => $expected) {
559 $resolved = CRM_Core_BAO_MessageTemplate::renderTemplate([
560 'messageTemplate' => [
f85e1a4b 561 'msg_text' => '{domain.now|crmDate:"' . $filter . '"}',
44dd64f0
EM
562 ],
563 ])['text'];
f85e1a4b 564 $this->assertEquals($expected, $resolved);
44dd64f0 565 }
defba8ff
EM
566 $resolved = CRM_Core_BAO_MessageTemplate::renderTemplate([
567 'messageTemplate' => [
568 'msg_text' => '{domain.now}',
569 ],
570 ])['text'];
571 $this->assertEquals('September 18th, 2021 11:58 PM', $resolved);
f85e1a4b
TO
572
573 // This example is malformed - no quotes
574 try {
575 $resolved = CRM_Core_BAO_MessageTemplate::renderTemplate([
576 'messageTemplate' => [
577 'msg_text' => '{domain.now|crmDate:shortdate}',
578 ],
579 ])['text'];
580 $this->fail("Expected unquoted parameter to fail");
581 }
582 catch (\CRM_Core_Exception $e) {
583 $this->assertRegExp(';Malformed token param;', $e->getMessage());
584 }
defba8ff
EM
585 }
586
3c78698e
EM
587 /**
588 * Get declared participant tokens.
589 *
590 * @return string[]
591 */
592 public function getDomainTokens(): array {
593 return [
594 '{domain.name}' => ts('Domain name'),
595 '{domain.address}' => ts('Domain (organization) address'),
596 '{domain.phone}' => ts('Domain (organization) phone'),
597 '{domain.email}' => 'Domain (organization) email',
598 '{domain.id}' => ts('Domain ID'),
599 '{domain.description}' => ts('Domain Description'),
defba8ff 600 '{domain.now}' => 'Current time/date',
3c78698e
EM
601 ];
602 }
603
ce971869
EM
604 /**
605 * Test that domain tokens are consistently rendered.
34795e7a
EM
606 *
607 * @throws \API_Exception
ce971869
EM
608 */
609 public function testEventTokenConsistency(): void {
f399fbd8
EM
610 $mut = new CiviMailUtils($this);
611 $this->setupParticipantScheduledReminder();
612
ce971869
EM
613 $tokens = CRM_Core_SelectValues::eventTokens();
614 $this->assertEquals($this->getEventTokens(), $tokens);
615 $tokenProcessor = new TokenProcessor(\Civi::dispatcher(), [
616 'controller' => __CLASS__,
617 'smarty' => FALSE,
618 'schema' => ['eventId'],
619 ]);
620 $this->assertEquals(array_merge($tokens, $this->getDomainTokens()), $tokenProcessor->listTokens());
f399fbd8
EM
621
622 $this->callAPISuccess('job', 'send_reminder', []);
623 $expected = $this->getExpectedEventTokenOutput();
624 $mut->checkMailLog([$expected]);
625 }
626
627 /**
628 * Set up scheduled reminder for participants.
629 *
630 * @throws \API_Exception
631 */
632 public function setupParticipantScheduledReminder(): void {
633 $this->createCustomGroupWithFieldOfType(['extends' => 'Event']);
634 $emailID = Email::create()->setValues(['email' => 'event@example.com'])->execute()->first()['id'];
635 $addressID = Address::create()->setValues([
636 'street_address' => '15 Walton St',
637 'supplemental_address_1' => 'up the road',
638 'city' => 'Emerald City',
639 'state_province_id:label' => 'Maine',
640 'postal_code' => 90210,
641 ])->execute()->first()['id'];
642 $phoneID = Phone::create()->setValues(['phone' => '456 789'])->execute()->first()['id'];
643
644 $locationBlockID = LocBlock::save(FALSE)->setRecords([
645 [
646 'email_id' => $emailID,
647 'address_id' => $addressID,
648 'phone_id' => $phoneID,
649 ],
650 ])->execute()->first()['id'];
651 $event = $this->eventCreate([
652 'description' => 'event description',
653 $this->getCustomFieldName('text') => 'my field',
654 'loc_block_id' => $locationBlockID,
655 ]);
656 // Create an unrelated participant record so that the ids don't match.
657 // this prevents things working just because the id 'happens to be valid'
658 $this->participantCreate(['register_date' => '2020-01-01', 'event_id' => $event['id']]);
659 $this->participantCreate(['event_id' => $event['id'], 'fee_amount' => 50]);
660 CRM_Utils_Time::setTime('2007-02-20 15:00:00');
661 $this->callAPISuccess('action_schedule', 'create', [
662 'title' => 'job',
663 'subject' => 'job',
664 'entity_value' => 1,
665 'mapping_id' => 2,
666 'start_action_date' => 'register_date',
667 'start_action_offset' => 1,
668 'start_action_condition' => 'after',
669 'start_action_unit' => 'day',
670 'body_html' => implode("\n", array_keys($this->getEventTokens())),
671 ]);
ce971869
EM
672 }
673
674 /**
675 * Get expected event tokens.
676 *
677 * @return string[]
678 */
679 protected function getEventTokens(): array {
680 return [
681 '{event.event_id}' => 'Event ID',
682 '{event.title}' => 'Event Title',
683 '{event.start_date}' => 'Event Start Date',
684 '{event.end_date}' => 'Event End Date',
685 '{event.event_type}' => 'Event Type',
686 '{event.summary}' => 'Event Summary',
687 '{event.contact_email}' => 'Event Contact Email',
688 '{event.contact_phone}' => 'Event Contact Phone',
689 '{event.description}' => 'Event Description',
690 '{event.location}' => 'Event Location',
691 '{event.fee_amount}' => 'Event Fee',
692 '{event.info_url}' => 'Event Info URL',
693 '{event.registration_url}' => 'Event Registration URL',
694 '{event.balance}' => 'Event Balance',
f399fbd8 695 '{event.' . $this->getCustomFieldName('text') . '}' => 'Enter text here :: Group with field text',
ce971869
EM
696 ];
697 }
698
d0ce76fd 699}