Merge pull request #16098 from MegaphoneJon/event-23-correct
[civicrm-core.git] / tests / phpunit / CRM / Core / BAO / ActionScheduleTest.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
7d61e75f 4 | Copyright CiviCRM LLC. All rights reserved. |
6a488035 5 | |
7d61e75f
TO
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 |
6a488035 9 +--------------------------------------------------------------------+
d25dd0ee 10 */
6a488035 11
e9479dcf
EM
12/**
13 * Class CRM_Core_BAO_ActionScheduleTest
2a21d018 14 * @group ActionSchedule
acb109b7 15 * @group headless
2a21d018
TO
16 *
17 * There are additional tests for some specific entities in other classes:
18 * @see CRM_Activity_ActionMappingTest
19 * @see CRM_Contribute_ActionMapping_ByTypeTest
e9479dcf 20 */
6a488035 21class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
63e9c3fd 22
6a488035 23 /**
f8c3594b 24 * @var CiviMailUtils
6a488035 25 */
567b2076 26 public $mut;
cee19268 27
00be9182 28 public function setUp() {
6a488035
TO
29 parent::setUp();
30
6c6e6187 31 $this->mut = new CiviMailUtils($this, TRUE);
6a488035 32
9099cab3 33 $this->fixtures['rolling_membership_type'] = [
e08fae02
PH
34 'period_type' => 'rolling',
35 'duration_unit' => 'month',
36 'duration_interval' => '3',
37 'is_active' => 1,
38 'domain_id' => 1,
39 'financial_type_id' => 2,
9099cab3 40 ];
e08fae02 41
9099cab3
CW
42 $this->fixtures['rolling_membership'] = [
43 'membership_type_id' => [
6a488035
TO
44 'period_type' => 'rolling',
45 'duration_unit' => 'month',
46 'duration_interval' => '3',
47 'is_active' => 1,
9099cab3 48 ],
6a488035
TO
49 'join_date' => '20120315',
50 'start_date' => '20120315',
51 'end_date' => '20120615',
b29be8c2 52 'is_override' => 0,
9099cab3 53 ];
4b1efa1d 54
9099cab3
CW
55 $this->fixtures['rolling_membership_past'] = [
56 'membership_type_id' => [
4b1efa1d 57 'period_type' => 'rolling',
58 'duration_unit' => 'month',
59 'duration_interval' => '3',
60 'is_active' => 1,
9099cab3 61 ],
4b1efa1d 62 'join_date' => '20100310',
63 'start_date' => '20100310',
64 'end_date' => '20100610',
65 'is_override' => 'NULL',
9099cab3
CW
66 ];
67 $this->fixtures['participant'] = [
68 'event_id' => [
d3eae6ea
TO
69 'is_active' => 1,
70 'is_template' => 0,
71 'title' => 'Example Event',
72 'start_date' => '20120315',
73 'end_date' => '20120615',
9099cab3 74 ],
39b959db
SL
75 // Attendee.
76 'role_id' => '1',
77 // No-show.
78 'status_id' => '8',
9099cab3 79 ];
fe265b4e 80
9099cab3 81 $this->fixtures['phonecall'] = [
6a488035
TO
82 'status_id' => 1,
83 'activity_type_id' => 2,
84 'activity_date_time' => '20120615100000',
85 'is_current_revision' => 1,
86 'is_deleted' => 0,
9099cab3
CW
87 ];
88 $this->fixtures['contact'] = [
b29be8c2 89 'is_deceased' => 0,
6a488035
TO
90 'contact_type' => 'Individual',
91 'email' => 'test-member@example.com',
43ceab3f 92 'gender_id' => 'Female',
bba4f3f6
CB
93 'first_name' => 'Churmondleia',
94 'last_name' => 'Ōtākou',
9099cab3
CW
95 ];
96 $this->fixtures['contact_2'] = [
e08fae02
PH
97 'is_deceased' => 0,
98 'contact_type' => 'Individual',
99 'email' => 'test-contact-2@example.com',
100 'gender_id' => 'Male',
101 'first_name' => 'Fabble',
102 'last_name' => 'Fi',
9099cab3
CW
103 ];
104 $this->fixtures['contact_birthdate'] = [
43030baf
AH
105 'is_deceased' => 0,
106 'contact_type' => 'Individual',
107 'email' => 'test-bday@example.com',
108 'birth_date' => '20050707',
9099cab3
CW
109 ];
110 $this->fixtures['sched_activity_1day'] = [
6a488035
TO
111 'name' => 'One_Day_Phone_Call_Notice',
112 'title' => 'One Day Phone Call Notice',
84a3e359 113 'limit_to' => '1',
6a488035 114 'absolute_date' => NULL,
d19632b1
JP
115 'body_html' => '<p>1-Day (non-repeating) (for {activity.subject})</p>',
116 'body_text' => '1-Day (non-repeating) (for {activity.subject})',
6a488035
TO
117 'end_action' => NULL,
118 'end_date' => NULL,
119 'end_frequency_interval' => NULL,
120 'end_frequency_unit' => NULL,
121 'entity_status' => '1',
122 'entity_value' => '2',
123 'group_id' => NULL,
124 'is_active' => '1',
125 'is_repeat' => '0',
126 'mapping_id' => '1',
127 'msg_template_id' => NULL,
128 'recipient' => '2',
129 'recipient_listing' => NULL,
130 'recipient_manual' => NULL,
d19632b1 131 'record_activity' => 1,
6a488035
TO
132 'repetition_frequency_interval' => NULL,
133 'repetition_frequency_unit' => NULL,
134 'start_action_condition' => 'before',
135 'start_action_date' => 'activity_date_time',
136 'start_action_offset' => '1',
137 'start_action_unit' => 'day',
f8c3594b 138 'subject' => '1-Day (non-repeating) (about {activity.activity_type})',
9099cab3
CW
139 ];
140 $this->fixtures['sched_activity_1day_r'] = [
6a488035
TO
141 'name' => 'One_Day_Phone_Call_Notice_R',
142 'title' => 'One Day Phone Call Notice R',
84a3e359 143 'limit_to' => 1,
6a488035
TO
144 'absolute_date' => NULL,
145 'body_html' => '<p>1-Day (repeating)</p>',
146 'body_text' => '1-Day (repeating)',
147 'end_action' => 'after',
148 'end_date' => 'activity_date_time',
149 'end_frequency_interval' => '2',
150 'end_frequency_unit' => 'day',
151 'entity_status' => '1',
152 'entity_value' => '2',
153 'group_id' => NULL,
154 'is_active' => '1',
155 'is_repeat' => '1',
156 'mapping_id' => '1',
157 'msg_template_id' => NULL,
158 'recipient' => '2',
159 'recipient_listing' => NULL,
160 'recipient_manual' => NULL,
161 'record_activity' => NULL,
162 'repetition_frequency_interval' => '6',
163 'repetition_frequency_unit' => 'hour',
164 'start_action_condition' => 'before',
165 'start_action_date' => 'activity_date_time',
166 'start_action_offset' => '1',
167 'start_action_unit' => 'day',
f8c3594b 168 'subject' => '1-Day (repeating) (about {activity.activity_type})',
9099cab3
CW
169 ];
170 $this->fixtures['sched_activity_1day_r_on_abs_date'] = [
dc6c330d 171 'name' => 'One_Day_Phone_Call_Notice_R',
172 'title' => 'One Day Phone Call Notice R',
173 'limit_to' => 1,
174 'absolute_date' => CRM_Utils_Date::processDate('20120614100000'),
175 'body_html' => '<p>1-Day (repeating)</p>',
176 'body_text' => '1-Day (repeating)',
177 'entity_status' => '1',
178 'entity_value' => '2',
179 'group_id' => NULL,
180 'is_active' => '1',
181 'is_repeat' => '1',
182 'mapping_id' => '1',
183 'msg_template_id' => NULL,
184 'recipient' => '2',
185 'recipient_listing' => NULL,
186 'recipient_manual' => NULL,
187 'record_activity' => NULL,
188 'repetition_frequency_interval' => '6',
189 'repetition_frequency_unit' => 'hour',
190 'end_action' => 'after',
191 'end_date' => 'activity_date_time',
192 'end_frequency_interval' => '2',
193 'end_frequency_unit' => 'day',
194 'start_action_condition' => '',
195 'start_action_date' => '',
196 'start_action_offset' => '',
197 'start_action_unit' => '',
198 'subject' => '1-Day (repeating) (about {activity.activity_type})',
9099cab3
CW
199 ];
200 $this->fixtures['sched_eventname_1day_on_abs_date'] = [
e08fae02
PH
201 'name' => 'sched_eventname_1day_on_abs_date',
202 'title' => 'sched_eventname_1day_on_abs_date',
203 'limit_to' => 1,
204 'absolute_date' => CRM_Utils_Date::processDate('20120614100000'),
205 'body_html' => '<p>sched_eventname_1day_on_abs_date</p>',
206 'body_text' => 'sched_eventname_1day_on_abs_date',
207 'entity_status' => '1',
208 'entity_value' => '2',
209 'group_id' => NULL,
210 'is_active' => '1',
211 'is_repeat' => '0',
212 'mapping_id' => '3',
213 'msg_template_id' => NULL,
214 'recipient' => '2',
215 'recipient_listing' => NULL,
216 'recipient_manual' => NULL,
217 'record_activity' => NULL,
218 'repetition_frequency_interval' => NULL,
219 'repetition_frequency_unit' => NULL,
220 'end_action' => NULL,
221 'end_date' => NULL,
222 'end_frequency_interval' => NULL,
223 'end_frequency_unit' => NULL,
224 'start_action_condition' => NULL,
225 'start_action_date' => NULL,
226 'start_action_offset' => NULL,
227 'start_action_unit' => NULL,
228 'subject' => 'sched_eventname_1day_on_abs_date',
9099cab3
CW
229 ];
230 $this->fixtures['sched_membership_join_2week'] = [
6a488035
TO
231 'name' => 'sched_membership_join_2week',
232 'title' => 'sched_membership_join_2week',
233 'absolute_date' => '',
234 'body_html' => '<p>body sched_membership_join_2week</p>',
235 'body_text' => 'body sched_membership_join_2week',
236 'end_action' => '',
237 'end_date' => '',
238 'end_frequency_interval' => '',
239 'end_frequency_unit' => '',
240 'entity_status' => '',
241 'entity_value' => '',
242 'group_id' => '',
243 'is_active' => 1,
244 'is_repeat' => '0',
245 'mapping_id' => 4,
246 'msg_template_id' => '',
247 'recipient' => '',
248 'recipient_listing' => '',
249 'recipient_manual' => '',
250 'record_activity' => 1,
251 'repetition_frequency_interval' => '',
252 'repetition_frequency_unit' => '',
253 'start_action_condition' => 'after',
254 'start_action_date' => 'membership_join_date',
255 'start_action_offset' => '2',
256 'start_action_unit' => 'week',
f8c3594b 257 'subject' => 'subject sched_membership_join_2week (joined {membership.join_date})',
9099cab3
CW
258 ];
259 $this->fixtures['sched_membership_start_1week'] = [
bb3ba83e
AH
260 'name' => 'sched_membership_start_1week',
261 'title' => 'sched_membership_start_1week',
262 'absolute_date' => '',
263 'body_html' => '<p>body sched_membership_start_1week</p>',
264 'body_text' => 'body sched_membership_start_1week',
265 'end_action' => '',
266 'end_date' => '',
267 'end_frequency_interval' => '',
268 'end_frequency_unit' => '',
269 'entity_status' => '',
270 'entity_value' => '',
271 'group_id' => '',
272 'is_active' => 1,
273 'is_repeat' => '0',
274 'mapping_id' => 4,
275 'msg_template_id' => '',
276 'recipient' => '',
277 'recipient_listing' => '',
278 'recipient_manual' => '',
279 'record_activity' => 1,
280 'repetition_frequency_interval' => '',
281 'repetition_frequency_unit' => '',
282 'start_action_condition' => 'after',
283 'start_action_date' => 'membership_start_date',
284 'start_action_offset' => '1',
285 'start_action_unit' => 'week',
286 'subject' => 'subject sched_membership_start_1week (joined {membership.start_date})',
9099cab3
CW
287 ];
288 $this->fixtures['sched_membership_end_2week'] = [
6a488035
TO
289 'name' => 'sched_membership_end_2week',
290 'title' => 'sched_membership_end_2week',
291 'absolute_date' => '',
292 'body_html' => '<p>body sched_membership_end_2week</p>',
293 'body_text' => 'body sched_membership_end_2week',
294 'end_action' => '',
295 'end_date' => '',
296 'end_frequency_interval' => '',
297 'end_frequency_unit' => '',
298 'entity_status' => '',
299 'entity_value' => '',
300 'group_id' => '',
301 'is_active' => 1,
302 'is_repeat' => '0',
303 'mapping_id' => 4,
304 'msg_template_id' => '',
305 'recipient' => '',
306 'recipient_listing' => '',
307 'recipient_manual' => '',
308 'record_activity' => 1,
309 'repetition_frequency_interval' => '',
310 'repetition_frequency_unit' => '',
311 'start_action_condition' => 'before',
312 'start_action_date' => 'membership_end_date',
313 'start_action_offset' => '2',
314 'start_action_unit' => 'week',
315 'subject' => 'subject sched_membership_end_2week',
9099cab3
CW
316 ];
317 $this->fixtures['sched_on_membership_end_date'] = [
d2868251 318 'name' => 'sched_on_membership_end_date',
319 'title' => 'sched_on_membership_end_date',
320 'body_html' => '<p>Your membership expired today</p>',
321 'body_text' => 'Your membership expired today',
322 'is_active' => 1,
323 'mapping_id' => 4,
324 'record_activity' => 1,
325 'start_action_condition' => 'after',
326 'start_action_date' => 'membership_end_date',
327 'start_action_offset' => '0',
328 'start_action_unit' => 'hour',
329 'subject' => 'subject send reminder on membership_end_date',
9099cab3
CW
330 ];
331 $this->fixtures['sched_after_1day_membership_end_date'] = [
d2868251 332 'name' => 'sched_after_1day_membership_end_date',
333 'title' => 'sched_after_1day_membership_end_date',
334 'body_html' => '<p>Your membership expired yesterday</p>',
335 'body_text' => 'Your membership expired yesterday',
336 'is_active' => 1,
337 'mapping_id' => 4,
338 'record_activity' => 1,
339 'start_action_condition' => 'after',
340 'start_action_date' => 'membership_end_date',
341 'start_action_offset' => '1',
342 'start_action_unit' => 'day',
343 'subject' => 'subject send reminder on membership_end_date',
9099cab3 344 ];
4b1efa1d 345
9099cab3 346 $this->fixtures['sched_membership_end_2month'] = [
4b1efa1d 347 'name' => 'sched_membership_end_2month',
348 'title' => 'sched_membership_end_2month',
349 'absolute_date' => '',
350 'body_html' => '<p>body sched_membership_end_2month</p>',
351 'body_text' => 'body sched_membership_end_2month',
352 'end_action' => '',
353 'end_date' => '',
354 'end_frequency_interval' => '',
355 'end_frequency_unit' => '',
356 'entity_status' => '',
357 'entity_value' => '',
358 'group_id' => '',
359 'is_active' => 1,
360 'is_repeat' => '0',
361 'mapping_id' => 4,
362 'msg_template_id' => '',
363 'recipient' => '',
364 'recipient_listing' => '',
365 'recipient_manual' => '',
366 'record_activity' => 1,
367 'repetition_frequency_interval' => '',
368 'repetition_frequency_unit' => '',
369 'start_action_condition' => 'after',
370 'start_action_date' => 'membership_end_date',
371 'start_action_offset' => '2',
372 'start_action_unit' => 'month',
373 'subject' => 'subject sched_membership_end_2month',
9099cab3 374 ];
4b1efa1d 375
9099cab3 376 $this->fixtures['sched_membership_absolute_date'] = [
e08fae02
PH
377 'name' => 'sched_membership_absolute_date',
378 'title' => 'sched_membership_absolute_date',
379 'absolute_date' => CRM_Utils_Date::processDate('20120614100000'),
380 'body_html' => '<p>body sched_membership_absolute_date</p>',
381 'body_text' => 'body sched_membership_absolute_date',
382 'end_action' => '',
383 'end_date' => '',
384 'end_frequency_interval' => '',
385 'end_frequency_unit' => '',
386 'entity_status' => '',
387 'entity_value' => '',
388 'group_id' => '',
389 'is_active' => 1,
390 'is_repeat' => '0',
391 'mapping_id' => 4,
392 'msg_template_id' => '',
393 'recipient' => '',
394 'recipient_listing' => '',
395 'recipient_manual' => '',
396 'record_activity' => 1,
397 'repetition_frequency_interval' => '',
398 'repetition_frequency_unit' => '',
399 'start_action_condition' => '',
400 'start_action_date' => '',
401 'start_action_offset' => '',
402 'start_action_unit' => '',
403 'subject' => 'subject sched_membership_absolute_date',
9099cab3 404 ];
e08fae02 405
9099cab3 406 $this->fixtures['sched_contact_bday_yesterday'] = [
43030baf
AH
407 'name' => 'sched_contact_bday_yesterday',
408 'title' => 'sched_contact_bday_yesterday',
409 'absolute_date' => '',
410 'body_html' => '<p>you look like you were born yesterday!</p>',
411 'body_text' => 'you look like you were born yesterday!',
412 'end_action' => '',
413 'end_date' => '',
414 'end_frequency_interval' => '',
415 'end_frequency_unit' => '',
416 'entity_status' => 1,
417 'entity_value' => 'birth_date',
418 'group_id' => '',
419 'is_active' => 1,
420 'is_repeat' => '0',
421 'mapping_id' => 6,
422 'msg_template_id' => '',
423 'recipient' => '',
424 'recipient_listing' => '',
425 'recipient_manual' => '',
426 'record_activity' => 1,
427 'repetition_frequency_interval' => '',
428 'repetition_frequency_unit' => '',
429 'start_action_condition' => 'after',
430 'start_action_date' => 'date_field',
431 'start_action_offset' => '1',
432 'start_action_unit' => 'day',
433 'subject' => 'subject sched_contact_bday_yesterday',
9099cab3 434 ];
43030baf 435
9099cab3 436 $this->fixtures['sched_contact_bday_anniv'] = [
43030baf
AH
437 'name' => 'sched_contact_bday_anniv',
438 'title' => 'sched_contact_bday_anniv',
439 'absolute_date' => '',
440 'body_html' => '<p>happy birthday!</p>',
441 'body_text' => 'happy birthday!',
442 'end_action' => '',
443 'end_date' => '',
444 'end_frequency_interval' => '',
445 'end_frequency_unit' => '',
446 'entity_status' => 2,
447 'entity_value' => 'birth_date',
448 'group_id' => '',
449 'is_active' => 1,
450 'is_repeat' => '0',
451 'mapping_id' => 6,
452 'msg_template_id' => '',
453 'recipient' => '',
454 'recipient_listing' => '',
455 'recipient_manual' => '',
456 'record_activity' => 1,
457 'repetition_frequency_interval' => '',
458 'repetition_frequency_unit' => '',
459 'start_action_condition' => 'before',
460 'start_action_date' => 'date_field',
461 'start_action_offset' => '1',
462 'start_action_unit' => 'day',
463 'subject' => 'subject sched_contact_bday_anniv',
9099cab3 464 ];
43030baf 465
9099cab3 466 $this->fixtures['sched_contact_grad_tomorrow'] = [
43030baf
AH
467 'name' => 'sched_contact_grad_tomorrow',
468 'title' => 'sched_contact_grad_tomorrow',
469 'absolute_date' => '',
470 'body_html' => '<p>congratulations on your graduation!</p>',
471 'body_text' => 'congratulations on your graduation!',
472 'end_action' => '',
473 'end_date' => '',
474 'end_frequency_interval' => '',
475 'end_frequency_unit' => '',
476 'entity_status' => 1,
477 'group_id' => '',
478 'is_active' => 1,
479 'is_repeat' => '0',
480 'mapping_id' => 6,
481 'msg_template_id' => '',
482 'recipient' => '',
483 'recipient_listing' => '',
484 'recipient_manual' => '',
485 'record_activity' => 1,
486 'repetition_frequency_interval' => '',
487 'repetition_frequency_unit' => '',
488 'start_action_condition' => 'before',
489 'start_action_date' => 'date_field',
490 'start_action_offset' => '1',
491 'start_action_unit' => 'day',
492 'subject' => 'subject sched_contact_grad_tomorrow',
9099cab3 493 ];
43030baf 494
9099cab3 495 $this->fixtures['sched_contact_grad_anniv'] = [
43030baf
AH
496 'name' => 'sched_contact_grad_anniv',
497 'title' => 'sched_contact_grad_anniv',
498 'absolute_date' => '',
499 'body_html' => '<p>dear alum, please send us money.</p>',
500 'body_text' => 'dear alum, please send us money.',
501 'end_action' => '',
502 'end_date' => '',
503 'end_frequency_interval' => '',
504 'end_frequency_unit' => '',
505 'entity_status' => 2,
506 'group_id' => '',
507 'is_active' => 1,
508 'is_repeat' => '0',
509 'mapping_id' => 6,
510 'msg_template_id' => '',
511 'recipient' => '',
512 'recipient_listing' => '',
513 'recipient_manual' => '',
514 'record_activity' => 1,
515 'repetition_frequency_interval' => '',
516 'repetition_frequency_unit' => '',
517 'start_action_condition' => 'after',
518 'start_action_date' => 'date_field',
519 'start_action_offset' => '1',
520 'start_action_unit' => 'week',
521 'subject' => 'subject sched_contact_grad_anniv',
9099cab3 522 ];
4aff0253 523
9099cab3 524 $this->fixtures['sched_contact_created_yesterday'] = [
4aff0253
AH
525 'name' => 'sched_contact_created_yesterday',
526 'title' => 'sched_contact_created_yesterday',
527 'absolute_date' => '',
528 'body_html' => '<p>Your contact was created yesterday</p>',
529 'body_text' => 'Your contact was created yesterday!',
530 'end_action' => '',
531 'end_date' => '',
532 'end_frequency_interval' => '',
533 'end_frequency_unit' => '',
534 'entity_status' => 1,
535 'entity_value' => 'created_date',
536 'group_id' => '',
537 'is_active' => 1,
538 'is_repeat' => '0',
539 'mapping_id' => 6,
540 'msg_template_id' => '',
541 'recipient' => '',
542 'recipient_listing' => '',
543 'recipient_manual' => '',
544 'record_activity' => 1,
545 'repetition_frequency_interval' => '',
546 'repetition_frequency_unit' => '',
547 'start_action_condition' => 'after',
548 'start_action_date' => 'date_field',
549 'start_action_offset' => '1',
550 'start_action_unit' => 'day',
551 'subject' => 'subject sched_contact_created_yesterday',
9099cab3 552 ];
4aff0253 553
9099cab3 554 $this->fixtures['sched_contact_mod_anniv'] = [
4aff0253
AH
555 'name' => 'sched_contact_mod_anniv',
556 'title' => 'sched_contact_mod_anniv',
557 'absolute_date' => '',
558 'body_html' => '<p>You last updated your data last year</p>',
559 'body_text' => 'Go update your stuff!',
560 'end_action' => '',
561 'end_date' => '',
562 'end_frequency_interval' => '',
563 'end_frequency_unit' => '',
564 'entity_status' => 2,
565 'entity_value' => 'modified_date',
566 'group_id' => '',
567 'is_active' => 1,
568 'is_repeat' => '0',
569 'mapping_id' => 6,
570 'msg_template_id' => '',
571 'recipient' => '',
572 'recipient_listing' => '',
573 'recipient_manual' => '',
574 'record_activity' => 1,
575 'repetition_frequency_interval' => '',
576 'repetition_frequency_unit' => '',
577 'start_action_condition' => 'before',
578 'start_action_date' => 'date_field',
579 'start_action_offset' => '1',
580 'start_action_unit' => 'day',
581 'subject' => 'subject sched_contact_mod_anniv',
9099cab3 582 ];
4aff0253 583
9099cab3 584 $this->fixtures['sched_eventtype_start_1week_before'] = [
d3eae6ea
TO
585 'name' => 'sched_eventtype_start_1week_before',
586 'title' => 'sched_eventtype_start_1week_before',
587 'absolute_date' => '',
588 'body_html' => '<p>body sched_eventtype_start_1week_before ({event.title})</p>',
589 'body_text' => 'body sched_eventtype_start_1week_before ({event.title})',
590 'end_action' => '',
591 'end_date' => '',
592 'end_frequency_interval' => '',
593 'end_frequency_unit' => '',
39b959db
SL
594 // participant status id
595 'entity_status' => '',
596 // event type id
597 'entity_value' => '',
d3eae6ea
TO
598 'group_id' => '',
599 'is_active' => 1,
600 'is_repeat' => '0',
39b959db
SL
601 // event type
602 'mapping_id' => 2,
d3eae6ea
TO
603 'msg_template_id' => '',
604 'recipient' => '',
605 'recipient_listing' => '',
606 'recipient_manual' => '',
607 'record_activity' => 1,
608 'repetition_frequency_interval' => '',
609 'repetition_frequency_unit' => '',
610 'start_action_condition' => 'before',
611 'start_action_date' => 'event_start_date',
612 'start_action_offset' => '1',
613 'start_action_unit' => 'week',
614 'subject' => 'subject sched_eventtype_start_1week_before ({event.title})',
9099cab3
CW
615 ];
616 $this->fixtures['sched_eventtype_end_2month_repeat_twice_2_weeks'] = [
d3eae6ea
TO
617 'name' => 'sched_eventtype_end_2month_repeat_twice_2_weeks',
618 'title' => 'sched_eventtype_end_2month_repeat_twice_2_weeks',
619 'absolute_date' => '',
620 'body_html' => '<p>body sched_eventtype_end_2month_repeat_twice_2_weeks {event.title}</p>',
621 'body_text' => 'body sched_eventtype_end_2month_repeat_twice_2_weeks {event.title}',
622 'end_action' => 'after',
623 'end_date' => 'event_end_date',
624 'end_frequency_interval' => '3',
625 'end_frequency_unit' => 'month',
39b959db
SL
626 // participant status id
627 'entity_status' => '',
628 // event type id
629 'entity_value' => '',
d3eae6ea
TO
630 'group_id' => '',
631 'is_active' => 1,
632 'is_repeat' => '1',
39b959db
SL
633 // event type
634 'mapping_id' => 2,
d3eae6ea
TO
635 'msg_template_id' => '',
636 'recipient' => '',
637 'recipient_listing' => '',
638 'recipient_manual' => '',
639 'record_activity' => 1,
640 'repetition_frequency_interval' => '2',
641 'repetition_frequency_unit' => 'week',
642 'start_action_condition' => 'after',
643 'start_action_date' => 'event_end_date',
644 'start_action_offset' => '2',
645 'start_action_unit' => 'month',
646 'subject' => 'subject sched_eventtype_end_2month_repeat_twice_2_weeks {event.title}',
9099cab3 647 ];
d3eae6ea 648
9099cab3 649 $this->fixtures['sched_membership_end_2month_repeat_twice_4_weeks'] = [
861d11c4
DG
650 'name' => 'sched_membership_end_2month',
651 'title' => 'sched_membership_end_2month',
652 'absolute_date' => '',
653 'body_html' => '<p>body sched_membership_end_2month</p>',
654 'body_text' => 'body sched_membership_end_2month',
655 'end_action' => '',
5c4d6559 656 'end_date' => 'membership_end_date',
861d11c4
DG
657 'end_frequency_interval' => '4',
658 'end_frequency_unit' => 'month',
659 'entity_status' => '',
660 'entity_value' => '',
661 'group_id' => '',
662 'is_active' => 1,
663 'is_repeat' => '1',
664 'mapping_id' => 4,
665 'msg_template_id' => '',
666 'recipient' => '',
667 'recipient_listing' => '',
668 'recipient_manual' => '',
669 'record_activity' => 1,
670 'repetition_frequency_interval' => '4',
671 'repetition_frequency_unit' => 'week',
672 'start_action_condition' => 'after',
673 'start_action_date' => 'membership_end_date',
674 'start_action_offset' => '2',
675 'start_action_unit' => 'month',
676 'subject' => 'subject sched_membership_end_2month',
9099cab3
CW
677 ];
678 $this->fixtures['sched_membership_end_limit_to_none'] = [
baa85770
EM
679 'name' => 'limit to none',
680 'title' => 'limit to none',
681 'absolute_date' => '',
682 'body_html' => '<p>body sched_membership_end_2month</p>',
683 'body_text' => 'body sched_membership_end_2month',
684 'end_action' => '',
685 'end_date' => '',
686 'end_frequency_interval' => '4',
687 'end_frequency_unit' => 'month',
688 'entity_status' => '',
689 'entity_value' => '',
690 'limit_to' => 0,
691 'group_id' => '',
692 'is_active' => 1,
693 'is_repeat' => '1',
694 'mapping_id' => 4,
695 'msg_template_id' => '',
696 'recipient' => '',
697 'recipient_listing' => '',
698 'recipient_manual' => '',
699 'record_activity' => 1,
700 'repetition_frequency_interval' => '4',
701 'repetition_frequency_unit' => 'week',
702 'start_action_condition' => 'after',
703 'start_action_date' => 'membership_end_date',
704 'start_action_offset' => '2',
705 'start_action_unit' => 'month',
706 'subject' => 'limit to none',
9099cab3
CW
707 ];
708 $this->fixtures['sched_on_membership_end_date_repeat_interval'] = [
52f09320
PH
709 'name' => 'sched_on_membership_end_date',
710 'title' => 'sched_on_membership_end_date',
711 'body_html' => '<p>Your membership expired 1 unit ago</p>',
712 'body_text' => 'Your membership expired 1 unit ago',
713 'end_frequency_interval' => 10,
714 'end_frequency_unit' => 'year',
715 'is_active' => 1,
716 'is_repeat' => TRUE,
717 'mapping_id' => 4,
718 'record_activity' => 1,
719 'start_action_condition' => 'after',
720 'start_action_date' => 'membership_end_date',
721 'start_action_offset' => '0',
722 'start_action_unit' => 'hour',
723 'subject' => 'subject send reminder every unit after membership_end_date',
9099cab3 724 ];
52f09320 725
9099cab3 726 $customGroup = $this->callAPISuccess('CustomGroup', 'create', [
2273ddcb 727 'title' => ts('Test Contact Custom group'),
728 'name' => 'test_contact_cg',
729 'extends' => 'Contact',
730 'domain_id' => CRM_Core_Config::domainID(),
731 'is_active' => 1,
732 'collapse_adv_display' => 0,
733 'collapse_display' => 0,
9099cab3
CW
734 ]);
735 $customField = $this->callAPISuccess('CustomField', 'create', [
2273ddcb 736 'label' => 'Test Text',
737 'data_type' => 'String',
738 'html_type' => 'Text',
739 'custom_group_id' => $customGroup['id'],
9099cab3
CW
740 ]);
741 $this->fixtures['contact_custom_token'] = [
2273ddcb 742 'id' => $customField['id'],
743 'token' => sprintf('{contact.custom_%s}', $customField['id']),
744 'name' => sprintf('custom_%s', $customField['id']),
745 'value' => 'text ' . substr(sha1(rand()), 0, 7),
9099cab3 746 ];
2273ddcb 747
6a488035 748 $this->_setUp();
6a488035
TO
749 }
750
751 /**
752 * Tears down the fixture, for example, closes a network connection.
92c99a4a 753 *
6a488035 754 * This method is called after a test is executed.
6a488035 755 */
00be9182 756 public function tearDown() {
6a488035 757 parent::tearDown();
6a488035
TO
758 $this->mut->clearMessages();
759 $this->mut->stop();
760 unset($this->mut);
9099cab3 761 $this->quickCleanup([
92c99a4a
EM
762 'civicrm_action_schedule',
763 'civicrm_action_log',
764 'civicrm_membership',
d3eae6ea
TO
765 'civicrm_participant',
766 'civicrm_event',
92c99a4a 767 'civicrm_email',
9099cab3
CW
768 ]);
769 $this->callAPISuccess('CustomField', 'delete', ['id' => $this->fixtures['contact_custom_token']['id']]);
770 $this->callAPISuccess('CustomGroup', 'delete', [
2273ddcb 771 'id' => CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomGroup', 'test_contact_cg', 'id', 'name'),
9099cab3 772 ]);
6a488035
TO
773 $this->_tearDown();
774 }
775
43ceab3f 776 public function mailerExamples() {
9099cab3 777 $cases = [];
43ceab3f 778
bba4f3f6 779 // Some tokens - short as subject has 128char limit in DB.
9099cab3 780 $someTokensTmpl = implode(';;', [
39b959db
SL
781 // basic contact token
782 '{contact.display_name}',
783 // funny legacy contact token
784 '{contact.gender}',
785 // funny legacy contact token
786 '{contact.gender_id}',
787 // domain token
788 '{domain.name}',
789 // action-scheduler token
790 '{activity.activity_type}',
9099cab3 791 ]);
bba4f3f6 792 // Further tokens can be tested in the body text/html.
9099cab3 793 $manyTokensTmpl = implode(';;', [
bba4f3f6
CB
794 $someTokensTmpl,
795 '{contact.email_greeting}',
2273ddcb 796 $this->fixture['contact_custom_token']['token'],
9099cab3 797 ]);
ccdf6bd5
TO
798 // Note: The behavior of domain-tokens on a scheduled reminder is undefined. All we
799 // can really do is check that it has something.
bba4f3f6 800 $someTokensExpected = 'Churmondleia Ōtākou;;Female;;Female;;[a-zA-Z0-9 ]+;;Phone Call';
2273ddcb 801 $manyTokensExpected = sprintf('%s;;Dear Churmondleia;;%s', $someTokensExpected, $this->fixture['contact_custom_token']['value']);
43ceab3f 802
bba4f3f6 803 // In this example, we use a lot of tokens cutting across multiple components.
9099cab3 804 $cases[0] = [
43ceab3f 805 // Schedule definition.
9099cab3 806 [
bba4f3f6 807 'subject' => "subj $someTokensTmpl",
43ceab3f
TO
808 'body_html' => "html $manyTokensTmpl",
809 'body_text' => "text $manyTokensTmpl",
9099cab3 810 ],
43ceab3f 811 // Assertions (regex).
9099cab3 812 [
43ceab3f
TO
813 'from_name' => "/^FIXME\$/",
814 'from_email' => "/^info@EXAMPLE.ORG\$/",
bba4f3f6 815 'subject' => "/^subj $someTokensExpected\$/",
43ceab3f
TO
816 'body_html' => "/^html $manyTokensExpected\$/",
817 'body_text' => "/^text $manyTokensExpected\$/",
9099cab3
CW
818 ],
819 ];
43ceab3f
TO
820
821 // In this example, we customize the from address.
9099cab3 822 $cases[1] = [
43ceab3f 823 // Schedule definition.
9099cab3 824 [
43ceab3f
TO
825 'from_name' => 'Bob',
826 'from_email' => 'bob@example.org',
9099cab3 827 ],
43ceab3f 828 // Assertions (regex).
9099cab3 829 [
43ceab3f
TO
830 'from_name' => "/^Bob\$/",
831 'from_email' => "/^bob@example.org\$/",
9099cab3
CW
832 ],
833 ];
43ceab3f
TO
834
835 // In this example, we autoconvert HTML to text
9099cab3 836 $cases[2] = [
43ceab3f 837 // Schedule definition.
9099cab3 838 [
43ceab3f
TO
839 'body_html' => '<p>Hello &amp; stuff.</p>',
840 'body_text' => '',
9099cab3 841 ],
43ceab3f 842 // Assertions (regex).
9099cab3 843 [
43ceab3f
TO
844 'body_html' => '/^' . preg_quote('<p>Hello &amp; stuff.</p>', '/') . '/',
845 'body_text' => '/^' . preg_quote('Hello & stuff.', '/') . '/',
9099cab3
CW
846 ],
847 ];
43ceab3f
TO
848
849 // In this example, we autoconvert HTML to text
9099cab3 850 $cases[3] = [
43ceab3f 851 // Schedule definition.
9099cab3 852 [
43ceab3f
TO
853 'body_html' => '',
854 'body_text' => 'Hello world',
9099cab3 855 ],
43ceab3f 856 // Assertions (regex).
9099cab3 857 [
43ceab3f
TO
858 'body_html' => '/^--UNDEFINED--$/',
859 'body_text' => '/^Hello world$/',
9099cab3
CW
860 ],
861 ];
43ceab3f
TO
862
863 return $cases;
864 }
865
866 /**
867 * This generates a single mailing through the scheduled-reminder
868 * system (using an activity-reminder as a baseline) and
869 * checks that the resulting message satisfies various
870 * regular expressions.
871 *
872 * @param array $schedule
873 * Values to set/override in the schedule.
874 * Ex: array('subject' => 'Hello, {contact.first_name}!').
875 * @param array $patterns
876 * A list of regexes to compare with the actual email.
877 * Ex: array('subject' => '/^Hello, Alice!/').
878 * Keys: subject, body_text, body_html, from_name, from_email.
879 * @dataProvider mailerExamples
880 */
881 public function testMailer($schedule, $patterns) {
882 $actionSchedule = array_merge($this->fixtures['sched_activity_1day'], $schedule);
883 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
884 $this->assertTrue(is_numeric($actionScheduleDao->id));
885
886 $activity = $this->createTestObject('CRM_Activity_DAO_Activity', $this->fixtures['phonecall']);
887 $this->assertTrue(is_numeric($activity->id));
2273ddcb 888 $contact = $this->callAPISuccess('contact', 'create', array_merge(
889 $this->fixtures['contact'],
9099cab3 890 [
2273ddcb 891 $this->fixtures['contact_custom_token']['name'] => $this->fixtures['contact_custom_token']['value'],
9099cab3 892 ]
2273ddcb 893 ));
43ceab3f
TO
894 $activity->save();
895
896 $source['contact_id'] = $contact['id'];
897 $source['activity_id'] = $activity->id;
898 $source['record_type_id'] = 2;
899 $activityContact = $this->createTestObject('CRM_Activity_DAO_ActivityContact', $source);
900 $activityContact->save();
901
902 CRM_Utils_Time::setTime('2012-06-14 15:00:00');
9099cab3
CW
903 $this->callAPISuccess('job', 'send_reminder', []);
904 $this->mut->assertRecipients([['test-member@example.com']]);
43ceab3f
TO
905 foreach ($this->mut->getAllMessages('ezc') as $message) {
906 /** @var ezcMail $message */
907
9099cab3 908 $messageArray = [];
43ceab3f
TO
909 $messageArray['subject'] = $message->subject;
910 $messageArray['from_name'] = $message->from->name;
911 $messageArray['from_email'] = $message->from->email;
912 $messageArray['body_text'] = '--UNDEFINED--';
913 $messageArray['body_html'] = '--UNDEFINED--';
914
915 foreach ($message->fetchParts() as $part) {
916 /** @var ezcMailText ezcMailText */
917 if ($part instanceof ezcMailText && $part->subType == 'html') {
918 $messageArray['body_html'] = $part->text;
919 }
920 if ($part instanceof ezcMailText && $part->subType == 'plain') {
921 $messageArray['body_text'] = $part->text;
922 }
923 }
924
925 foreach ($patterns as $field => $pattern) {
926 $this->assertRegExp($pattern, $messageArray[$field],
9099cab3 927 "Check that '$field'' matches regex. " . print_r(['expected' => $patterns, 'actual' => $messageArray], 1));
43ceab3f
TO
928 }
929 }
930 $this->mut->clearMessages();
43ceab3f
TO
931 }
932
92c99a4a 933 public function testActivityDateTimeMatchNonRepeatableSchedule() {
cee19268 934 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($this->fixtures['sched_activity_1day']);
6a488035
TO
935 $this->assertTrue(is_numeric($actionScheduleDao->id));
936
937 $activity = $this->createTestObject('CRM_Activity_DAO_Activity', $this->fixtures['phonecall']);
6a488035 938 $this->assertTrue(is_numeric($activity->id));
6c6e6187 939 $contact = $this->callAPISuccess('contact', 'create', $this->fixtures['contact']);
d19632b1 940 $activity->subject = "Test subject for Phonecall";
6a488035
TO
941 $activity->save();
942
4f20f356 943 $source['contact_id'] = $contact['id'];
944 $source['activity_id'] = $activity->id;
945 $source['record_type_id'] = 2;
946 $activityContact = $this->createTestObject('CRM_Activity_DAO_ActivityContact', $source);
947 $activityContact->save();
948
9099cab3
CW
949 $this->assertCronRuns([
950 [
567b2076 951 // Before the 24-hour mark, no email
6a488035 952 'time' => '2012-06-14 04:00:00',
9099cab3
CW
953 'recipients' => [],
954 'subjects' => [],
955 ],
956 [
567b2076 957 // After the 24-hour mark, an email
6a488035 958 'time' => '2012-06-14 15:00:00',
9099cab3
CW
959 'recipients' => [['test-member@example.com']],
960 'subjects' => ['1-Day (non-repeating) (about Phone Call)'],
961 ],
962 [
567b2076 963 // Run cron again; message already sent
6a488035 964 'time' => '',
9099cab3
CW
965 'recipients' => [],
966 ],
967 ]);
d19632b1
JP
968 $activityTypes = CRM_Core_PseudoConstant::activityType(TRUE, FALSE, FALSE, 'name');
969 $activityDAO = new CRM_Activity_DAO_Activity();
970 $activityDAO->source_record_id = $activity->id;
971 $activityDAO->activity_type_id = array_search('Reminder Sent', $activityTypes);
972 $activityDAO->find();
973 while ($activityDAO->fetch()) {
974 $this->assertContains($activity->subject, $activityDAO->details);
975 }
6a488035
TO
976 }
977
92c99a4a 978 public function testActivityDateTimeMatchRepeatableSchedule() {
cee19268 979 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($this->fixtures['sched_activity_1day_r']);
6a488035
TO
980 $this->assertTrue(is_numeric($actionScheduleDao->id));
981
982 $activity = $this->createTestObject('CRM_Activity_DAO_Activity', $this->fixtures['phonecall']);
983 $this->assertTrue(is_numeric($activity->id));
6c6e6187 984 $contact = $this->callAPISuccess('contact', 'create', $this->fixtures['contact']);
6a488035
TO
985 $activity->save();
986
4f20f356 987 $source['contact_id'] = $contact['id'];
988 $source['activity_id'] = $activity->id;
6c6e6187 989 $source['record_type_id'] = 2;
4f20f356 990 $activityContact = $this->createTestObject('CRM_Activity_DAO_ActivityContact', $source);
991 $activityContact->save();
992
9099cab3
CW
993 $this->assertCronRuns([
994 [
567b2076 995 // Before the 24-hour mark, no email
6a488035 996 'time' => '012-06-14 04:00:00',
9099cab3
CW
997 'recipients' => [],
998 'subjects' => [],
999 ],
1000 [
567b2076 1001 // After the 24-hour mark, an email
6a488035 1002 'time' => '2012-06-14 15:00:00',
9099cab3
CW
1003 'recipients' => [['test-member@example.com']],
1004 'subjects' => ['1-Day (repeating) (about Phone Call)'],
1005 ],
1006 [
567b2076 1007 // Run cron 4 hours later; first message already sent
6a488035 1008 'time' => '2012-06-14 20:00:00',
9099cab3
CW
1009 'recipients' => [],
1010 'subjects' => [],
1011 ],
1012 [
567b2076 1013 // Run cron 6 hours later; send second message.
6a488035 1014 'time' => '2012-06-14 21:00:01',
9099cab3
CW
1015 'recipients' => [['test-member@example.com']],
1016 'subjects' => ['1-Day (repeating) (about Phone Call)'],
1017 ],
1018 ]);
6a488035
TO
1019 }
1020
dc6c330d 1021 public function testActivityDateTimeMatchRepeatableScheduleOnAbsDate() {
1022 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($this->fixtures['sched_activity_1day_r_on_abs_date']);
1023 $this->assertTrue(is_numeric($actionScheduleDao->id));
1024
1025 $activity = $this->createTestObject('CRM_Activity_DAO_Activity', $this->fixtures['phonecall']);
1026 $this->assertTrue(is_numeric($activity->id));
1027 $contact = $this->callAPISuccess('contact', 'create', $this->fixtures['contact']);
1028 $activity->save();
1029
1030 $source['contact_id'] = $contact['id'];
1031 $source['activity_id'] = $activity->id;
1032 $source['record_type_id'] = 2;
1033 $activityContact = $this->createTestObject('CRM_Activity_DAO_ActivityContact', $source);
1034 $activityContact->save();
1035
9099cab3
CW
1036 $this->assertCronRuns([
1037 [
dc6c330d 1038 // Before the 24-hour mark, no email
1039 'time' => '2012-06-13 04:00:00',
9099cab3
CW
1040 'recipients' => [],
1041 'subjects' => [],
1042 ],
1043 [
dc6c330d 1044 // On absolute date set on 2012-06-14
1045 'time' => '2012-06-14 00:00:00',
9099cab3
CW
1046 'recipients' => [['test-member@example.com']],
1047 'subjects' => ['1-Day (repeating) (about Phone Call)'],
1048 ],
1049 [
dc6c330d 1050 // Run cron 4 hours later; first message already sent
1051 'time' => '2012-06-14 04:00:00',
9099cab3
CW
1052 'recipients' => [],
1053 'subjects' => [],
1054 ],
1055 [
dc6c330d 1056 // Run cron 6 hours later; send second message.
1057 'time' => '2012-06-14 06:00:01',
9099cab3
CW
1058 'recipients' => [['test-member@example.com']],
1059 'subjects' => ['1-Day (repeating) (about Phone Call)'],
1060 ],
1061 ]);
dc6c330d 1062 }
1063
e08fae02 1064 public function testEventNameWithAbsoluteDateAndNothingElse() {
9099cab3
CW
1065 $participant = $this->createTestObject('CRM_Event_DAO_Participant', array_merge($this->fixtures['participant'], ['status_id' => 1]));
1066 $this->callAPISuccess('Email', 'create', [
e08fae02
PH
1067 'contact_id' => $participant->contact_id,
1068 'email' => 'test-event@example.com',
9099cab3
CW
1069 ]);
1070 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], ['contact_id' => $participant->contact_id]));
e08fae02
PH
1071
1072 $actionSchedule = $this->fixtures['sched_eventname_1day_on_abs_date'];
1073 $actionSchedule['entity_value'] = $participant->event_id;
1074 $this->callAPISuccess('action_schedule', 'create', $actionSchedule);
1075
9099cab3
CW
1076 $this->assertCronRuns([
1077 [
e08fae02
PH
1078 // Before the 24-hour mark, no email
1079 'time' => '2012-06-13 04:00:00',
9099cab3
CW
1080 'recipients' => [],
1081 'subjects' => [],
1082 ],
1083 [
e08fae02
PH
1084 // On absolute date set on 2012-06-14
1085 'time' => '2012-06-14 00:00:00',
9099cab3
CW
1086 'recipients' => [['test-event@example.com']],
1087 'subjects' => ['sched_eventname_1day_on_abs_date'],
1088 ],
1089 [
e08fae02
PH
1090 // Run cron 4 hours later; first message already sent
1091 'time' => '2012-06-14 04:00:00',
9099cab3
CW
1092 'recipients' => [],
1093 'subjects' => [],
1094 ],
1095 ]);
e08fae02
PH
1096 }
1097
6a488035
TO
1098 /**
1099 * For contacts/activities which don't match the schedule filter,
1100 * an email should *not* be sent.
1101 */
1102 // TODO // function testActivityDateTime_NonMatch() { }
1103
1104 /**
76ea51c7 1105 * For contacts/members which match schedule based on join/start date,
6a488035
TO
1106 * an email should be sent.
1107 */
76ea51c7 1108 public function testMembershipDateMatch() {
9099cab3 1109 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], ['status_id' => 1]));
bb3ba83e 1110 $this->assertTrue(is_numeric($membership->id));
9099cab3 1111 $result = $this->callAPISuccess('Email', 'create', [
bb3ba83e
AH
1112 'contact_id' => $membership->contact_id,
1113 'email' => 'test-member@example.com',
1114 'location_type_id' => 1,
1115 'is_primary' => 1,
9099cab3 1116 ]);
6a488035 1117
9099cab3 1118 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], ['contact_id' => $membership->contact_id]));
bb3ba83e
AH
1119 $actionSchedule = $this->fixtures['sched_membership_join_2week'];
1120 $actionSchedule['entity_value'] = $membership->membership_type_id;
1121 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
1122 $this->assertTrue(is_numeric($actionScheduleDao->id));
6a488035 1123
bb3ba83e 1124 // start_date=2012-03-15 ; schedule is 2 weeks after join_date
9099cab3
CW
1125 $this->assertCronRuns([
1126 [
bb3ba83e
AH
1127 // Before the 2-week mark, no email.
1128 'time' => '2012-03-28 01:00:00',
9099cab3
CW
1129 'recipients' => [],
1130 'subjects' => [],
1131 ],
1132 [
bb3ba83e
AH
1133 // After the 2-week mark, send an email.
1134 'time' => '2012-03-29 01:00:00',
9099cab3
CW
1135 'recipients' => [['test-member@example.com']],
1136 'subjects' => ['subject sched_membership_join_2week (joined March 15th, 2012)'],
1137 ],
1138 ]);
bb3ba83e
AH
1139
1140 $actionSchedule = $this->fixtures['sched_membership_start_1week'];
1141 $actionSchedule['entity_value'] = $membership->membership_type_id;
1142 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
1143 $this->assertTrue(is_numeric($actionScheduleDao->id));
1144
1145 // start_date=2012-03-15 ; schedule is 1 weeks after start_date
9099cab3
CW
1146 $this->assertCronRuns([
1147 [
bb3ba83e
AH
1148 // Before the 2-week mark, no email.
1149 'time' => '2012-03-21 01:00:00',
9099cab3
CW
1150 'recipients' => [],
1151 'subjects' => [],
1152 ],
1153 [
bb3ba83e
AH
1154 // After the 2-week mark, send an email.
1155 'time' => '2012-03-22 01:00:00',
9099cab3
CW
1156 'recipients' => [['test-member@example.com']],
1157 'subjects' => ['subject sched_membership_start_1week (joined March 15th, 2012)'],
1158 ],
1159 ]);
6a488035
TO
1160 }
1161
cc949606 1162 /**
1163 * CRM-21675: Support parent and smart group in 'Limit to' field
1164 */
1165 public function testScheduleReminderWithParentGroup() {
1166 // Contact A with birth-date at '07-07-2005' and gender - Male, later got added in smart group
9099cab3 1167 $contactID1 = $this->individualCreate(['birth_date' => '20050707', 'gender_id' => 1, 'email' => 'abc@test.com']);
cc949606 1168 // Contact B with birth-date at '07-07-2005', later got added in regular group
9099cab3 1169 $contactID2 = $this->individualCreate(['birth_date' => '20050707', 'email' => 'def@test.com'], 1);
cc949606 1170 // Contact C with birth-date at '07-07-2005', but not included in any group
9099cab3 1171 $contactID3 = $this->individualCreate(['birth_date' => '20050707', 'email' => 'ghi@test.com'], 2);
cc949606 1172
1173 // create regular group and add Contact B to it
1174 $groupID = $this->groupCreate();
9099cab3 1175 $this->callAPISuccess('GroupContact', 'Create', [
cc949606 1176 'group_id' => $groupID,
1177 'contact_id' => $contactID2,
9099cab3 1178 ]);
cc949606 1179
1180 // create smart group which will contain all Male contacts
9099cab3 1181 $smartGroupParams = ['formValues' => ['gender_id' => 1]];
cc949606 1182 $smartGroupID = $this->smartGroupCreate(
1183 $smartGroupParams,
9099cab3 1184 [
cc949606 1185 'name' => 'new_smart_group',
1186 'title' => 'New Smart Group',
9099cab3
CW
1187 'parents' => [$groupID => 1],
1188 ]
cc949606 1189 );
1190
9099cab3 1191 $actionScheduleParams = [
cc949606 1192 'name' => 'sched_contact_bday_yesterday',
1193 'title' => 'sched_contact_bday_yesterday',
1194 'absolute_date' => '',
1195 'body_html' => '<p>you look like you were born yesterday!</p>',
1196 'body_text' => 'you look like you were born yesterday!',
1197 'end_action' => '',
1198 'end_date' => '',
1199 'end_frequency_interval' => '',
1200 'end_frequency_unit' => '',
1201 'entity_status' => 1,
1202 'entity_value' => 'birth_date',
1203 'limit_to' => 1,
1204 'group_id' => $groupID,
1205 'is_active' => 1,
1206 'is_repeat' => '0',
1207 'mapping_id' => 6,
1208 'msg_template_id' => '',
1209 'recipient' => '2',
1210 'recipient_listing' => '',
1211 'recipient_manual' => '',
1212 'record_activity' => 1,
1213 'repetition_frequency_interval' => '',
1214 'repetition_frequency_unit' => '',
1215 'start_action_condition' => 'after',
1216 'start_action_date' => 'date_field',
1217 'start_action_offset' => '1',
1218 'start_action_unit' => 'day',
1219 'subject' => 'subject sched_contact_bday_yesterday',
9099cab3 1220 ];
cc949606 1221
1222 // Create schedule reminder where parent group ($groupID) is selectd to limit recipients,
1223 // which contain a individual contact - $contactID2 and is parent to smart group.
1224 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionScheduleParams);
1225 $this->assertTrue(is_numeric($actionScheduleDao->id));
9099cab3
CW
1226 $this->assertCronRuns([
1227 [
cc949606 1228 // On the birthday, no email.
1229 'time' => '2005-07-07 01:00:00',
9099cab3
CW
1230 'recipients' => [],
1231 ],
1232 [
cc949606 1233 // The next day, send an email.
1234 'time' => '2005-07-08 20:00:00',
9099cab3
CW
1235 'recipients' => [
1236 [
cc949606 1237 'def@test.com',
9099cab3
CW
1238 ],
1239 [
cc949606 1240 'abc@test.com',
9099cab3
CW
1241 ],
1242 ],
1243 ],
1244 ]);
cc949606 1245 $this->groupDelete($smartGroupID);
1246 $this->groupDelete($groupID);
1247 }
1248
6a488035 1249 /**
442cf836
EM
1250 * Test end date email sent.
1251 *
6a488035
TO
1252 * For contacts/members which match schedule based on join date,
1253 * an email should be sent.
1254 */
92c99a4a 1255 public function testMembershipJoinDateNonMatch() {
6a488035
TO
1256 $membership = $this->createTestObject('CRM_Member_DAO_Membership', $this->fixtures['rolling_membership']);
1257 $this->assertTrue(is_numeric($membership->id));
9099cab3 1258 $result = $this->callAPISuccess('Email', 'create', [
6a488035
TO
1259 'contact_id' => $membership->contact_id,
1260 'location_type_id' => 1,
1261 'email' => 'test-member@example.com',
9099cab3 1262 ]);
fe265b4e 1263
6a488035 1264 // Add an alternative membership type, and only send messages for that type
9099cab3 1265 $extraMembershipType = $this->createTestObject('CRM_Member_DAO_MembershipType', []);
6a488035 1266 $this->assertTrue(is_numeric($extraMembershipType->id));
cee19268 1267 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($this->fixtures['sched_membership_join_2week']);
6a488035
TO
1268 $this->assertTrue(is_numeric($actionScheduleDao->id));
1269 $actionScheduleDao->entity_value = $extraMembershipType->id;
1270 $actionScheduleDao->save();
1271
1272 // start_date=2012-03-15 ; schedule is 2 weeks after start_date
9099cab3
CW
1273 $this->assertCronRuns([
1274 [
567b2076 1275 // After the 2-week mark, don't send email because we have different membership type.
6a488035 1276 'time' => '2012-03-29 01:00:00',
9099cab3
CW
1277 'recipients' => [],
1278 ],
1279 ]);
6a488035
TO
1280 }
1281
861d11c4 1282 /**
442cf836 1283 * Test that the first and SECOND notifications are sent out.
861d11c4 1284 */
92c99a4a 1285 public function testMembershipEndDateRepeat() {
861d11c4 1286 // creates membership with end_date = 20120615
9099cab3
CW
1287 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], ['status_id' => 2]));
1288 $result = $this->callAPISuccess('Email', 'create', [
861d11c4
DG
1289 'contact_id' => $membership->contact_id,
1290 'email' => 'test-member@example.com',
9099cab3
CW
1291 ]);
1292 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], ['contact_id' => $membership->contact_id]));
861d11c4
DG
1293
1294 $actionSchedule = $this->fixtures['sched_membership_end_2month_repeat_twice_4_weeks'];
1295 $actionSchedule['entity_value'] = $membership->membership_type_id;
1296 $this->callAPISuccess('action_schedule', 'create', $actionSchedule);
1297
1298 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
9099cab3
CW
1299 $this->assertCronRuns([
1300 [
e08fae02
PH
1301 // After the 1-month mark, no email
1302 'time' => '2012-07-15 01:00:00',
9099cab3
CW
1303 'recipients' => [],
1304 ],
1305 [
e08fae02 1306 // After the 2-month mark, send an email.
861d11c4 1307 'time' => '2012-08-15 01:00:00',
9099cab3
CW
1308 'recipients' => [['test-member@example.com']],
1309 ],
1310 [
e08fae02 1311 // 4 weeks after first email send first repeat
861d11c4 1312 'time' => '2012-09-12 01:00:00',
9099cab3
CW
1313 'recipients' => [['test-member@example.com']],
1314 ],
1315 [
e08fae02
PH
1316 // 1 week after first repeat send nothing
1317 // There was a bug where the first repeat went out and then
1318 // it would keep going out every cron run. This is to check that's
1319 // not happening.
1320 'time' => '2012-09-19 01:00:00',
9099cab3
CW
1321 'recipients' => [],
1322 ],
1323 [
e08fae02
PH
1324 // 4 weeks after first repeat send second repeat
1325 'time' => '2012-10-10 01:00:00',
9099cab3
CW
1326 'recipients' => [['test-member@example.com']],
1327 ],
1328 [
e08fae02
PH
1329 // 4 months after membership end, send nothing
1330 'time' => '2012-10-15 01:00:00',
9099cab3
CW
1331 'recipients' => [],
1332 ],
1333 [
e08fae02
PH
1334 // 5 months after membership end, send nothing
1335 'time' => '2012-11-15 01:00:00',
9099cab3
CW
1336 'recipients' => [],
1337 ],
1338 ]);
861d11c4
DG
1339 }
1340
1341 /**
442cf836
EM
1342 * Test behaviour when date changes.
1343 *
861d11c4
DG
1344 * Test that the first notification is sent but the second is NOT sent if the end date changes in
1345 * between
1346 * see CRM-15376
1347 */
92c99a4a 1348 public function testMembershipEndDateRepeatChangedEndDate_CRM_15376() {
861d11c4 1349 // creates membership with end_date = 20120615
9099cab3
CW
1350 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], ['status_id' => 2]));
1351 $this->callAPISuccess('Email', 'create', [
861d11c4
DG
1352 'contact_id' => $membership->contact_id,
1353 'email' => 'test-member@example.com',
9099cab3
CW
1354 ]);
1355 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], ['contact_id' => $membership->contact_id]));
861d11c4
DG
1356
1357 $actionSchedule = $this->fixtures['sched_membership_end_2month_repeat_twice_4_weeks'];
1358 $actionSchedule['entity_value'] = $membership->membership_type_id;
1359 $this->callAPISuccess('action_schedule', 'create', $actionSchedule);
1360 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
9099cab3
CW
1361 $this->assertCronRuns([
1362 [
567b2076 1363 // After the 2-week mark, send an email.
861d11c4 1364 'time' => '2012-08-15 01:00:00',
9099cab3
CW
1365 'recipients' => [['test-member@example.com']],
1366 ],
1367 ]);
861d11c4 1368
442cf836 1369 // Extend membership - reminder should NOT go out.
9099cab3
CW
1370 $this->callAPISuccess('membership', 'create', ['id' => $membership->id, 'end_date' => '2014-01-01']);
1371 $this->assertCronRuns([
1372 [
442cf836 1373 // After the 2-week mark, send an email.
861d11c4 1374 'time' => '2012-09-12 01:00:00',
9099cab3
CW
1375 'recipients' => [],
1376 ],
1377 ]);
861d11c4
DG
1378 }
1379
6a488035 1380 /**
442cf836
EM
1381 * Test membership end date email sends.
1382 *
6a488035
TO
1383 * For contacts/members which match schedule based on end date,
1384 * an email should be sent.
1385 */
92c99a4a 1386 public function testMembershipEndDateMatch() {
6a488035 1387 // creates membership with end_date = 20120615
9099cab3 1388 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], ['status_id' => 2]));
6a488035 1389 $this->assertTrue(is_numeric($membership->id));
9099cab3 1390 $this->callAPISuccess('Email', 'create', [
6a488035
TO
1391 'contact_id' => $membership->contact_id,
1392 'email' => 'test-member@example.com',
9099cab3
CW
1393 ]);
1394 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], ['contact_id' => $membership->contact_id]));
6a488035
TO
1395
1396 $actionSchedule = $this->fixtures['sched_membership_end_2week'];
1397 $actionSchedule['entity_value'] = $membership->membership_type_id;
cee19268 1398 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
6a488035
TO
1399 $this->assertTrue(is_numeric($actionScheduleDao->id));
1400
1401 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
9099cab3
CW
1402 $this->assertCronRuns([
1403 [
442cf836 1404 // Before the 2-week mark, no email.
6a488035 1405 'time' => '2012-05-31 01:00:00',
9099cab3
CW
1406 'recipients' => [],
1407 ],
1408 [
442cf836 1409 // After the 2-week mark, send an email.
6a488035 1410 'time' => '2012-06-01 01:00:00',
9099cab3
CW
1411 'recipients' => [['test-member@example.com']],
1412 ],
1413 [
e08fae02
PH
1414 // After the email is sent, another one is not sent
1415 'time' => '2012-06-01 02:00:00',
9099cab3
CW
1416 'recipients' => [],
1417 ],
1418 ]);
d2868251 1419
1420 // Now suppose user has renewed for rolling membership after 3 months, so upcoming assertion is written
1421 // to ensure that new reminder is sent 2 week before the new end_date i.e. '2012-09-15'
1422 $membership->end_date = '2012-09-15';
1423 $membership->save();
1424
1425 //change the email id of chosen membership contact to assert
1426 //recipient of not the previously sent mail but the new one
9099cab3 1427 $result = $this->callAPISuccess('Email', 'create', [
d2868251 1428 'is_primary' => 1,
1429 'contact_id' => $membership->contact_id,
cbcb7579 1430 'email' => 'member2@example.com',
9099cab3 1431 ]);
d2868251 1432 $this->assertAPISuccess($result);
1433
1434 // end_date=2012-09-15 ; schedule is 2 weeks before end_date
9099cab3
CW
1435 $this->assertCronRuns([
1436 [
cbcb7579 1437 // Before the 2-week mark, no email
d2868251 1438 'time' => '2012-08-31 01:00:00',
9099cab3
CW
1439 'recipients' => [],
1440 ],
1441 [
e08fae02
PH
1442 // After the 2-week mark, send an email
1443 'time' => '2012-09-01 01:00:00',
9099cab3
CW
1444 'recipients' => [['member2@example.com']],
1445 ],
1446 [
e08fae02
PH
1447 // After the email is sent, another one is not sent
1448 'time' => '2012-09-01 02:00:00',
9099cab3
CW
1449 'recipients' => [],
1450 ],
1451 ]);
e08fae02
PH
1452
1453 $membership->end_date = '2012-12-15';
1454 $membership->save();
1455 // end_date=2012-12-15 ; schedule is 2 weeks before end_date
9099cab3
CW
1456 $this->assertCronRuns([
1457 [
e08fae02
PH
1458 // Before the 2-week mark, no email
1459 'time' => '2012-11-30 01:00:00',
9099cab3
CW
1460 'recipients' => [],
1461 ],
1462 [
e08fae02
PH
1463 // After the 2-week mark, send an email
1464 'time' => '2012-12-01 01:00:00',
9099cab3
CW
1465 'recipients' => [['member2@example.com']],
1466 ],
1467 [
e08fae02
PH
1468 // After the email is sent, another one is not sent
1469 'time' => '2012-12-01 02:00:00',
9099cab3
CW
1470 'recipients' => [],
1471 ],
1472 ]);
e08fae02
PH
1473
1474 }
1475
1476 public function createMembershipAndContact($contactFixture, $membershipTypeId) {
1477 $result = $this->callAPISuccess('contact', 'create', $contactFixture);
1478 $contact = $result['values'][$result['id']];
9099cab3 1479 $params = [
e08fae02
PH
1480 'status_id' => 2,
1481 'contact_id' => $contact['id'],
1482 'membership_type_id' => $membershipTypeId,
1483 'owner_membership_id' => 'NULL',
9099cab3 1484 ];
e08fae02
PH
1485 $params = array_merge($this->fixtures['rolling_membership'], $params);
1486 $membership = $this->createTestObject('CRM_Member_DAO_Membership', $params);
1487 $this->assertTrue(is_numeric($membership->id));
1488 return $membership;
1489 }
1490
1491 /**
1492 * This test is very similar to testMembershipEndDateMatch, but it adds
1493 * another contact because there was a bug in
1494 * RecipientBuilder::buildRelFirstPass where it was only sending the
1495 * reminder for the first contact returned in a query for renewed
1496 * memberships. Other contacts wouldn't get the mail.
1497 */
1498 public function testMultipleMembershipEndDateMatch() {
1499 $membershipTypeId = $this->membershipTypeCreate($this->fixtures['rolling_membership']['membership_type_id']);
1500 $membershipOne = $this->createMembershipAndContact($this->fixtures['contact'], $membershipTypeId);
1501 $membershipTwo = $this->createMembershipAndContact($this->fixtures['contact_2'], $membershipTypeId);
1502 $actionSchedule = $this->fixtures['sched_membership_end_2week'];
1503 $actionSchedule['entity_value'] = $membershipTypeId;
1504 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
1505 $this->assertTrue(is_numeric($actionScheduleDao->id));
1506
1507 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
9099cab3
CW
1508 $this->assertCronRuns([
1509 [
e08fae02
PH
1510 // Before the 2-week mark, no email.
1511 'time' => '2012-05-31 01:00:00',
9099cab3
CW
1512 'recipients' => [],
1513 ],
1514 [
e08fae02
PH
1515 // After the 2-week mark, send emails.
1516 'time' => '2012-06-01 01:00:00',
9099cab3
CW
1517 'recipients' => [
1518 ['test-member@example.com'],
1519 ['test-contact-2@example.com'],
1520 ],
1521 ],
1522 [
e08fae02
PH
1523 // After the email is sent, another one is not sent
1524 'time' => '2012-06-01 02:00:00',
9099cab3
CW
1525 'recipients' => [],
1526 ],
1527 ]);
e08fae02
PH
1528
1529 // Now suppose user has renewed for rolling membership after 3 months, so upcoming assertion is written
1530 // to ensure that new reminder is sent 2 week before the new end_date i.e. '2012-09-15'
1531 $membershipOne->end_date = '2012-09-15';
1532 $membershipOne->save();
1533 $membershipTwo->end_date = '2012-09-15';
1534 $membershipTwo->save();
1535
1536 // end_date=2012-09-15 ; schedule is 2 weeks before end_date
9099cab3
CW
1537 $this->assertCronRuns([
1538 [
e08fae02
PH
1539 // Before the 2-week mark, no email
1540 'time' => '2012-08-31 01:00:00',
9099cab3
CW
1541 'recipients' => [],
1542 ],
1543 [
e08fae02
PH
1544 // After the 2-week mark, send an email
1545 'time' => '2012-09-01 01:00:00',
9099cab3
CW
1546 'recipients' => [
1547 ['test-member@example.com'],
1548 ['test-contact-2@example.com'],
1549 ],
1550 ],
1551 [
e08fae02
PH
1552 // After the email is sent, another one is not sent
1553 'time' => '2012-06-01 02:00:00',
9099cab3
CW
1554 'recipients' => [],
1555 ],
1556 ]);
6a488035
TO
1557 }
1558
4b1efa1d 1559 /**
442cf836
EM
1560 * Test membership end date email.
1561 *
6c6e6187
TO
1562 * For contacts/members which match schedule based on end date,
1563 * an email should be sent.
1564 */
92c99a4a 1565 public function testMembershipEndDateNoMatch() {
4b1efa1d 1566 // creates membership with end_date = 20120615
9099cab3 1567 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], ['status_id' => 3]));
4b1efa1d 1568 $this->assertTrue(is_numeric($membership->id));
9099cab3 1569 $result = $this->callAPISuccess('Email', 'create', [
4b1efa1d 1570 'contact_id' => $membership->contact_id,
1571 'email' => 'test-member@example.com',
9099cab3
CW
1572 ]);
1573 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], ['contact_id' => $membership->contact_id]));
4b1efa1d 1574
1575 $actionSchedule = $this->fixtures['sched_membership_end_2month'];
1576 $actionSchedule['entity_value'] = $membership->membership_type_id;
cee19268 1577 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
4b1efa1d 1578 $this->assertTrue(is_numeric($actionScheduleDao->id));
1579
1580 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
9099cab3
CW
1581 $this->assertCronRuns([
1582 [
442cf836 1583 // Before the 2-week mark, no email.
4b1efa1d 1584 'time' => '2012-05-31 01:00:00',
9099cab3
CW
1585 'recipients' => [],
1586 ],
1587 [
e08fae02 1588 // After the 2-week mark, no email
4b1efa1d 1589 'time' => '2013-05-01 01:00:00',
9099cab3
CW
1590 'recipients' => [],
1591 ],
1592 ]);
4b1efa1d 1593 }
1594
92c99a4a 1595 public function testContactBirthDateNoAnniv() {
bf308d29 1596 $contact = $this->callAPISuccess('Contact', 'create', $this->fixtures['contact_birthdate']);
43030baf
AH
1597 $this->_testObjects['CRM_Contact_DAO_Contact'][] = $contact['id'];
1598 $actionSchedule = $this->fixtures['sched_contact_bday_yesterday'];
1599 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
1600 $this->assertTrue(is_numeric($actionScheduleDao->id));
9099cab3
CW
1601 $this->assertCronRuns([
1602 [
442cf836 1603 // On the birthday, no email.
43030baf 1604 'time' => '2005-07-07 01:00:00',
9099cab3
CW
1605 'recipients' => [],
1606 ],
1607 [
442cf836 1608 // The next day, send an email.
43030baf 1609 'time' => '2005-07-08 20:00:00',
9099cab3
CW
1610 'recipients' => [['test-bday@example.com']],
1611 ],
1612 ]);
43030baf
AH
1613 }
1614
92c99a4a 1615 public function testContactBirthDateAnniversary() {
6c6e6187 1616 $contact = $this->callAPISuccess('Contact', 'create', $this->fixtures['contact_birthdate']);
43030baf
AH
1617 $this->_testObjects['CRM_Contact_DAO_Contact'][] = $contact['id'];
1618 $actionSchedule = $this->fixtures['sched_contact_bday_anniv'];
1619 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
1620 $this->assertTrue(is_numeric($actionScheduleDao->id));
9099cab3
CW
1621 $this->assertCronRuns([
1622 [
92c99a4a 1623 // On some random day, no email.
43030baf 1624 'time' => '2014-03-07 01:00:00',
9099cab3
CW
1625 'recipients' => [],
1626 ],
1627 [
92c99a4a 1628 // On the eve of their 9th birthday, send an email.
43030baf 1629 'time' => '2014-07-06 20:00:00',
9099cab3
CW
1630 'recipients' => [['test-bday@example.com']],
1631 ],
1632 ]);
43030baf 1633 }
4b1efa1d 1634
92c99a4a 1635 public function testContactCustomDateNoAnniv() {
9099cab3 1636 $group = [
43030baf
AH
1637 'title' => 'Test_Group',
1638 'name' => 'test_group',
9099cab3 1639 'extends' => ['Individual'],
43030baf 1640 'style' => 'Inline',
6c6e6187 1641 'is_multiple' => FALSE,
43030baf 1642 'is_active' => 1,
9099cab3 1643 ];
bf308d29 1644 $createGroup = $this->callAPISuccess('custom_group', 'create', $group);
9099cab3 1645 $field = [
43030baf
AH
1646 'label' => 'Graduation',
1647 'data_type' => 'Date',
1648 'html_type' => 'Select Date',
1649 'custom_group_id' => $createGroup['id'],
9099cab3 1650 ];
bf308d29 1651 $createField = $this->callAPISuccess('custom_field', 'create', $field);
43030baf
AH
1652 $contactParams = $this->fixtures['contact'];
1653 $contactParams["custom_{$createField['id']}"] = '2013-12-16';
bf308d29 1654 $contact = $this->callAPISuccess('Contact', 'create', $contactParams);
43030baf
AH
1655 $this->_testObjects['CRM_Contact_DAO_Contact'][] = $contact['id'];
1656 $actionSchedule = $this->fixtures['sched_contact_grad_tomorrow'];
1657 $actionSchedule['entity_value'] = "custom_{$createField['id']}";
1658 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
1659 $this->assertTrue(is_numeric($actionScheduleDao->id));
9099cab3
CW
1660 $this->assertCronRuns([
1661 [
92c99a4a 1662 // On some random day, no email.
43030baf 1663 'time' => '2014-03-07 01:00:00',
9099cab3
CW
1664 'recipients' => [],
1665 ],
1666 [
92c99a4a 1667 // On the eve of their graduation, send an email.
43030baf 1668 'time' => '2013-12-15 20:00:00',
9099cab3
CW
1669 'recipients' => [['test-member@example.com']],
1670 ],
1671 ]);
1672 $this->callAPISuccess('custom_group', 'delete', ['id' => $createGroup['id']]);
43030baf 1673 }
92915c55 1674
4aff0253
AH
1675 public function testContactCreatedNoAnniv() {
1676 $contact = $this->callAPISuccess('Contact', 'create', $this->fixtures['contact_birthdate']);
1677 $this->_testObjects['CRM_Contact_DAO_Contact'][] = $contact['id'];
1678 $actionSchedule = $this->fixtures['sched_contact_created_yesterday'];
1679 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
1680 $this->assertTrue(is_numeric($actionScheduleDao->id));
9099cab3
CW
1681 $this->assertCronRuns([
1682 [
4aff0253
AH
1683 // On the date created, no email.
1684 'time' => $contact['values'][$contact['id']]['created_date'],
9099cab3
CW
1685 'recipients' => [],
1686 ],
1687 [
4aff0253
AH
1688 // The next day, send an email.
1689 'time' => date('Y-m-d H:i:s', strtotime($contact['values'][$contact['id']]['created_date'] . ' +1 day')),
9099cab3
CW
1690 'recipients' => [['test-bday@example.com']],
1691 ],
1692 ]);
4aff0253
AH
1693 }
1694
1695 public function testContactModifiedAnniversary() {
1696 $contact = $this->callAPISuccess('Contact', 'create', $this->fixtures['contact_birthdate']);
1697 $this->_testObjects['CRM_Contact_DAO_Contact'][] = $contact['id'];
9099cab3 1698 $modifiedDate = $this->callAPISuccess('Contact', 'getvalue', ['id' => $contact['id'], 'return' => 'modified_date']);
4aff0253
AH
1699 $actionSchedule = $this->fixtures['sched_contact_mod_anniv'];
1700 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
1701 $this->assertTrue(is_numeric($actionScheduleDao->id));
9099cab3
CW
1702 $this->assertCronRuns([
1703 [
4aff0253 1704 // On some random day, no email.
a9ac9f6c 1705 'time' => date('Y-m-d H:i:s', strtotime($contact['values'][$contact['id']]['modified_date'] . ' -60 days')),
9099cab3
CW
1706 'recipients' => [],
1707 ],
1708 [
4aff0253 1709 // On the eve of 3 years after they were modified, send an email.
688bd604 1710 'time' => date('Y-m-d H:i:s', strtotime($modifiedDate . ' +3 years -1 day')),
9099cab3
CW
1711 'recipients' => [['test-bday@example.com']],
1712 ],
1713 ]);
4aff0253
AH
1714 }
1715
baa85770 1716 /**
92c99a4a 1717 * Check that limit_to + an empty recipients doesn't sent to multiple contacts.
baa85770 1718 */
00be9182 1719 public function testMembershipLimitToNone() {
baa85770 1720 // creates membership with end_date = 20120615
9099cab3 1721 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], ['status_id' => 2]));
baa85770
EM
1722
1723 $this->assertTrue(is_numeric($membership->id));
9099cab3 1724 $result = $this->callAPISuccess('Email', 'create', [
baa85770
EM
1725 'contact_id' => $membership->contact_id,
1726 'email' => 'member@example.com',
9099cab3
CW
1727 ]);
1728 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], ['contact_id' => $membership->contact_id]));
1729 $this->callAPISuccess('contact', 'create', ['email' => 'b@c.com', 'contact_type' => 'Individual']);
baa85770
EM
1730
1731 $this->assertAPISuccess($result);
1732
1733 $actionSchedule = $this->fixtures['sched_membership_end_limit_to_none'];
1734 $actionSchedule['entity_value'] = $membership->membership_type_id;
1735 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
1736 $this->assertTrue(is_numeric($actionScheduleDao->id));
1737
1738 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
9099cab3
CW
1739 $this->assertCronRuns([
1740 [
92c99a4a 1741 // Before the 2-week mark, no email.
baa85770
EM
1742 'time' => '2012-05-31 01:00:00',
1743 // 'time' => '2012-06-01 01:00:00', // FIXME: Is this the right boundary?
9099cab3
CW
1744 'recipients' => [],
1745 ],
1746 ]);
baa85770
EM
1747 }
1748
cbcb7579 1749 public function testMembership_referenceDate() {
9099cab3 1750 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], ['status_id' => 2]));
5c4d6559 1751
1752 $this->assertTrue(is_numeric($membership->id));
9099cab3 1753 $result = $this->callAPISuccess('Email', 'create', [
5c4d6559 1754 'contact_id' => $membership->contact_id,
1755 'email' => 'member@example.com',
9099cab3 1756 ]);
5c4d6559 1757
9099cab3 1758 $result = $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], ['contact_id' => $membership->contact_id]));
5c4d6559 1759 $this->assertAPISuccess($result);
1760
1761 $actionSchedule = $this->fixtures['sched_membership_join_2week'];
1762 $actionSchedule['entity_value'] = $membership->membership_type_id;
1763 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
1764 $this->assertTrue(is_numeric($actionScheduleDao->id));
1765
1766 // start_date=2012-03-15 ; schedule is 2 weeks after start_date
9099cab3
CW
1767 $this->assertCronRuns([
1768 [
cbcb7579 1769 // After the 2-week mark, send an email
5c4d6559 1770 'time' => '2012-03-29 01:00:00',
9099cab3
CW
1771 'recipients' => [['member@example.com']],
1772 ],
1773 [
cbcb7579 1774 // After the 2-week 1day mark, don't send an email
9c0fe051 1775 'time' => '2012-03-30 01:00:00',
9099cab3
CW
1776 'recipients' => [],
1777 ],
1778 ]);
5c4d6559 1779
1780 //check if reference date is set to membership's join date
1781 //as per the action_start_date chosen for current schedule reminder
e08fae02 1782 $this->assertEquals('2012-03-15 00:00:00',
5c4d6559 1783 CRM_Core_DAO::getFieldValue('CRM_Core_DAO_ActionLog', $membership->contact_id, 'reference_date', 'contact_id')
1784 );
1785
e7c6a902 1786 //change current membership join date that may signifies as membership renewal activity
5c4d6559 1787 $membership->join_date = '2012-03-29';
1788 $membership->save();
1789
9099cab3
CW
1790 $this->assertCronRuns([
1791 [
cbcb7579 1792 // After the 13 days of the changed join date 2012-03-29, don't send an email
9c0fe051 1793 'time' => '2012-04-11 01:00:00',
9099cab3
CW
1794 'recipients' => [],
1795 ],
1796 [
cbcb7579 1797 // After the 2-week of the changed join date 2012-03-29, send an email
5c4d6559 1798 'time' => '2012-04-12 01:00:00',
9099cab3
CW
1799 'recipients' => [['member@example.com']],
1800 ],
1801 ]);
1802 $this->assertCronRuns([
1803 [
7d48c97b 1804 // It should not re-send on the same day
1805 'time' => '2012-04-12 01:00:00',
9099cab3
CW
1806 'recipients' => [],
1807 ],
1808 ]);
5c4d6559 1809 }
baa85770 1810
d2868251 1811 public function testMembershipOnMultipleReminder() {
9099cab3 1812 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], ['status_id' => 2]));
d2868251 1813
1814 $this->assertTrue(is_numeric($membership->id));
9099cab3 1815 $result = $this->callAPISuccess('Email', 'create', [
d2868251 1816 'contact_id' => $membership->contact_id,
1817 'email' => 'member@example.com',
9099cab3
CW
1818 ]);
1819 $result = $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], ['contact_id' => $membership->contact_id]));
d2868251 1820 $this->assertAPISuccess($result);
1821
39b959db
SL
1822 // Send email 2 weeks before end_date
1823 $actionScheduleBefore = $this->fixtures['sched_membership_end_2week'];
1824 // Send email on end_date/expiry date
1825 $actionScheduleOn = $this->fixtures['sched_on_membership_end_date'];
1826 // Send email 1 day after end_date/grace period
1827 $actionScheduleAfter = $this->fixtures['sched_after_1day_membership_end_date'];
d2868251 1828 $actionScheduleBefore['entity_value'] = $actionScheduleOn['entity_value'] = $actionScheduleAfter['entity_value'] = $membership->membership_type_id;
9099cab3 1829 foreach (['actionScheduleBefore', 'actionScheduleOn', 'actionScheduleAfter'] as $value) {
d2868251 1830 $$value = CRM_Core_BAO_ActionSchedule::add($$value);
1831 $this->assertTrue(is_numeric($$value->id));
1832 }
1833
1834 $this->assertCronRuns(
9099cab3
CW
1835 [
1836 [
cbcb7579 1837 // 1day 2weeks before membership end date(MED), don't send mail
d2868251 1838 'time' => '2012-05-31 01:00:00',
9099cab3
CW
1839 'recipients' => [],
1840 ],
1841 [
cbcb7579 1842 // 2 weeks before MED, send an email
d2868251 1843 'time' => '2012-06-01 01:00:00',
9099cab3
CW
1844 'recipients' => [['member@example.com']],
1845 ],
1846 [
cbcb7579 1847 // 1day before MED, don't send mail
d2868251 1848 'time' => '2012-06-14 01:00:00',
9099cab3
CW
1849 'recipients' => [],
1850 ],
1851 [
cbcb7579 1852 // On MED, send an email
d2868251 1853 'time' => '2012-06-15 00:00:00',
9099cab3
CW
1854 'recipients' => [['member@example.com']],
1855 ],
1856 [
cbcb7579 1857 // After 1day of MED, send an email
d2868251 1858 'time' => '2012-06-16 01:00:00',
9099cab3
CW
1859 'recipients' => [['member@example.com']],
1860 ],
1861 [
cbcb7579 1862 // After 1day 1min of MED, don't send an email
d2868251 1863 'time' => '2012-06-17 00:01:00',
9099cab3
CW
1864 'recipients' => [],
1865 ],
1866 ]
cbcb7579 1867 );
d2868251 1868
1869 // Assert the timestamp as of when the emails of respective three reminders as configured
1870 // 2 weeks before, on and 1 day after MED, are sent
f42ab010
TO
1871 $this->assertApproxEquals(
1872 strtotime('2012-06-01 01:00:00'),
1873 strtotime(CRM_Core_DAO::getFieldValue('CRM_Core_DAO_ActionLog', $actionScheduleBefore->id, 'action_date_time', 'action_schedule_id', TRUE)),
39b959db
SL
1874 // Variation in test execution time.
1875 3
f42ab010
TO
1876 );
1877 $this->assertApproxEquals(
1878 strtotime('2012-06-15 00:00:00'),
1879 strtotime(CRM_Core_DAO::getFieldValue('CRM_Core_DAO_ActionLog', $actionScheduleOn->id, 'action_date_time', 'action_schedule_id', TRUE)),
39b959db
SL
1880 // Variation in test execution time.
1881 3
f42ab010
TO
1882 );
1883 $this->assertApproxEquals(
1884 strtotime('2012-06-16 01:00:00'),
1885 strtotime(CRM_Core_DAO::getFieldValue('CRM_Core_DAO_ActionLog', $actionScheduleAfter->id, 'action_date_time', 'action_schedule_id', TRUE)),
39b959db
SL
1886 // Variation in test execution time.
1887 3
f42ab010 1888 );
d2868251 1889
e7c6a902 1890 //extend MED to 2 weeks after the current MED (that may signifies as membership renewal activity)
d2868251 1891 // and lets assert as of when the new set of reminders will be sent against their respective Schedule Reminders(SR)
9c0fe051 1892 $membership->end_date = '2012-06-20';
d2868251 1893 $membership->save();
d2868251 1894
9099cab3 1895 $result = $this->callAPISuccess('Contact', 'get', ['id' => $membership->contact_id]);
d2868251 1896 $this->assertCronRuns(
9099cab3
CW
1897 [
1898 [
cbcb7579 1899 // 1day 2weeks before membership end date(MED), don't send mail
9c0fe051 1900 'time' => '2012-06-05 01:00:00',
9099cab3
CW
1901 'recipients' => [],
1902 ],
1903 [
cbcb7579 1904 // 2 weeks before MED, send an email
9c0fe051 1905 'time' => '2012-06-06 01:00:00',
9099cab3
CW
1906 'recipients' => [['member@example.com']],
1907 ],
1908 [
cbcb7579 1909 // 1day before MED, don't send mail
9c0fe051 1910 'time' => '2012-06-19 01:00:00',
9099cab3
CW
1911 'recipients' => [],
1912 ],
1913 [
cbcb7579 1914 // On MED, send an email
9c0fe051 1915 'time' => '2012-06-20 00:00:00',
9099cab3
CW
1916 'recipients' => [['member@example.com']],
1917 ],
1918 [
cbcb7579 1919 // After 1day of MED, send an email
9c0fe051 1920 'time' => '2012-06-21 01:00:00',
9099cab3
CW
1921 'recipients' => [['member@example.com']],
1922 ],
1923 [
cbcb7579 1924 // After 1day 1min of MED, don't send an email
9c0fe051 1925 'time' => '2012-07-21 00:01:00',
9099cab3
CW
1926 'recipients' => [],
1927 ],
1928 ]);
d2868251 1929 }
1930
1931 public function testContactCustomDate_Anniv() {
9099cab3 1932 $group = [
43030baf
AH
1933 'title' => 'Test_Group now',
1934 'name' => 'test_group_now',
9099cab3 1935 'extends' => ['Individual'],
43030baf 1936 'style' => 'Inline',
6c6e6187 1937 'is_multiple' => FALSE,
43030baf 1938 'is_active' => 1,
9099cab3 1939 ];
bf308d29 1940 $createGroup = $this->callAPISuccess('custom_group', 'create', $group);
9099cab3 1941 $field = [
43030baf
AH
1942 'label' => 'Graduation',
1943 'data_type' => 'Date',
1944 'html_type' => 'Select Date',
1945 'custom_group_id' => $createGroup['id'],
9099cab3 1946 ];
bf308d29
EM
1947 $createField = $this->callAPISuccess('custom_field', 'create', $field);
1948
43030baf
AH
1949 $contactParams = $this->fixtures['contact'];
1950 $contactParams["custom_{$createField['id']}"] = '2013-12-16';
bf308d29 1951 $contact = $this->callAPISuccess('Contact', 'create', $contactParams);
43030baf
AH
1952 $this->_testObjects['CRM_Contact_DAO_Contact'][] = $contact['id'];
1953 $actionSchedule = $this->fixtures['sched_contact_grad_anniv'];
1954 $actionSchedule['entity_value'] = "custom_{$createField['id']}";
1955 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
1956 $this->assertTrue(is_numeric($actionScheduleDao->id));
9099cab3
CW
1957 $this->assertCronRuns([
1958 [
92c99a4a 1959 // On some random day, no email.
43030baf 1960 'time' => '2014-03-07 01:00:00',
9099cab3
CW
1961 'recipients' => [],
1962 ],
1963 [
92c99a4a 1964 // A week after their 5th anniversary of graduation, send an email.
43030baf 1965 'time' => '2018-12-23 20:00:00',
9099cab3
CW
1966 'recipients' => [['test-member@example.com']],
1967 ],
1968 ]);
1969 $this->callAPISuccess('custom_group', 'delete', ['id' => $createGroup['id']]);
43030baf 1970 }
4b1efa1d 1971
76ea51c7
JP
1972 /**
1973 * Test sched reminder set via registration date.
1974 */
1975 public function testEventTypeRegistrationDate() {
1976 //Create contact
9099cab3 1977 $contactParams = [
76ea51c7 1978 'email' => 'test-event@example.com',
9099cab3 1979 ];
76ea51c7
JP
1980 $contact = $this->individualCreate($contactParams);
1981 //Add it as a participant to an event ending registration - 7 days from now.
9099cab3 1982 $params = [
76ea51c7
JP
1983 'start_date' => date('Ymd', strtotime('-5 day')),
1984 'end_date' => date('Ymd', strtotime('+7 day')),
1985 'registration_start_date' => date('Ymd', strtotime('-5 day')),
1986 'registration_end_date' => date('Ymd', strtotime('+7 day')),
9099cab3 1987 ];
76ea51c7 1988 $event = $this->eventCreate($params);
9099cab3 1989 $this->participantCreate(['contact_id' => $contact, 'event_id' => $event['id']]);
76ea51c7
JP
1990
1991 //Create a scheduled reminder to send email 7 days before registration date.
1992 $actionSchedule = $this->fixtures['sched_eventtype_start_1week_before'];
1993 $actionSchedule['start_action_offset'] = 7;
1994 $actionSchedule['start_action_unit'] = 'day';
1995 $actionSchedule['start_action_date'] = 'registration_end_date';
1996 $actionSchedule['entity_value'] = $event['values'][$event['id']]['event_type_id'];
9099cab3 1997 $actionSchedule['entity_status'] = $this->callAPISuccessGetValue('ParticipantStatusType', [
76ea51c7
JP
1998 'return' => "id",
1999 'name' => "Attended",
9099cab3 2000 ]);
899bd155 2001 $actionSched = $this->callAPISuccess('action_schedule', 'create', $actionSchedule);
76ea51c7 2002 //Run the cron and verify if an email was sent.
9099cab3
CW
2003 $this->assertCronRuns([
2004 [
76ea51c7 2005 'time' => date('Y-m-d'),
9099cab3
CW
2006 'recipients' => [['test-event@example.com']],
2007 ],
2008 ]);
899bd155
JP
2009
2010 //Create contact 2
9099cab3 2011 $contactParams = [
899bd155 2012 'email' => 'test-event2@example.com',
9099cab3 2013 ];
899bd155
JP
2014 $contact2 = $this->individualCreate($contactParams);
2015 //Create an event with registration end date = 2 week from now.
2016 $params['end_date'] = date('Ymd', strtotime('+2 week'));
2017 $params['registration_end_date'] = date('Ymd', strtotime('+2 week'));
2018 $event2 = $this->eventCreate($params);
9099cab3 2019 $this->participantCreate(['contact_id' => $contact2, 'event_id' => $event2['id']]);
899bd155
JP
2020
2021 //Assert there is no reminder sent to the contact.
9099cab3
CW
2022 $this->assertCronRuns([
2023 [
899bd155 2024 'time' => date('Y-m-d'),
9099cab3
CW
2025 'recipients' => [],
2026 ],
2027 ]);
899bd155
JP
2028
2029 //Modify the sched reminder to be sent 2 week from registration end date.
9099cab3 2030 $this->callAPISuccess('action_schedule', 'create', [
899bd155
JP
2031 'id' => $actionSched['id'],
2032 'start_action_offset' => 2,
2033 'start_action_unit' => 'week',
9099cab3 2034 ]);
899bd155
JP
2035
2036 //Contact should receive the reminder now.
9099cab3
CW
2037 $this->assertCronRuns([
2038 [
899bd155 2039 'time' => date('Y-m-d'),
9099cab3
CW
2040 'recipients' => [['test-event2@example.com']],
2041 ],
2042 ]);
76ea51c7
JP
2043 }
2044
2045 /**
2046 * Test sched reminder set via start date.
2047 */
d3eae6ea
TO
2048 public function testEventTypeStartDate() {
2049 // Create event+participant with start_date = 20120315, end_date = 20120615.
9099cab3
CW
2050 $participant = $this->createTestObject('CRM_Event_DAO_Participant', array_merge($this->fixtures['participant'], ['status_id' => 2]));
2051 $this->callAPISuccess('Email', 'create', [
d3eae6ea
TO
2052 'contact_id' => $participant->contact_id,
2053 'email' => 'test-event@example.com',
9099cab3
CW
2054 ]);
2055 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], ['contact_id' => $participant->contact_id]));
d3eae6ea
TO
2056
2057 $actionSchedule = $this->fixtures['sched_eventtype_start_1week_before'];
2058 $actionSchedule['entity_value'] = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $participant->event_id, 'event_type_id');
2059 $this->callAPISuccess('action_schedule', 'create', $actionSchedule);
2060
2061 //echo "CREATED\n"; ob_flush(); sleep(20);
2062
2063 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
9099cab3
CW
2064 $this->assertCronRuns([
2065 [
d3eae6ea
TO
2066 // 2 weeks before
2067 'time' => '2012-03-02 01:00:00',
9099cab3
CW
2068 'recipients' => [],
2069 ],
2070 [
d3eae6ea
TO
2071 // 1 week before
2072 'time' => '2012-03-08 01:00:00',
9099cab3
CW
2073 'recipients' => [['test-event@example.com']],
2074 ],
2075 [
d3eae6ea
TO
2076 // And then nothing else
2077 'time' => '2012-03-16 01:00:00',
9099cab3
CW
2078 'recipients' => [],
2079 ],
2080 ]);
d3eae6ea
TO
2081 }
2082
2083 public function testEventTypeEndDateRepeat() {
2084 // Create event+participant with start_date = 20120315, end_date = 20120615.
9099cab3
CW
2085 $participant = $this->createTestObject('CRM_Event_DAO_Participant', array_merge($this->fixtures['participant'], ['status_id' => 2]));
2086 $this->callAPISuccess('Email', 'create', [
d3eae6ea
TO
2087 'contact_id' => $participant->contact_id,
2088 'email' => 'test-event@example.com',
9099cab3
CW
2089 ]);
2090 $c = $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], ['contact_id' => $participant->contact_id]));
d3eae6ea
TO
2091
2092 $actionSchedule = $this->fixtures['sched_eventtype_end_2month_repeat_twice_2_weeks'];
2093 $actionSchedule['entity_value'] = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $participant->event_id, 'event_type_id');
2094 $this->callAPISuccess('action_schedule', 'create', $actionSchedule);
2095
9099cab3
CW
2096 $this->assertCronRuns([
2097 [
d3eae6ea
TO
2098 // Almost 2 months.
2099 'time' => '2012-08-13 01:00:00',
9099cab3
CW
2100 'recipients' => [],
2101 ],
2102 [
d3eae6ea
TO
2103 // After the 2-month mark, send an email.
2104 'time' => '2012-08-16 01:00:00',
9099cab3
CW
2105 'recipients' => [['test-event@example.com']],
2106 ],
2107 [
d3eae6ea
TO
2108 // After 2 months and 1 week, don't repeat yet.
2109 'time' => '2012-08-23 02:00:00',
9099cab3
CW
2110 'recipients' => [],
2111 ],
2112 [
d3eae6ea
TO
2113 // After 2 months and 2 weeks
2114 'time' => '2012-08-30 02:00:00',
9099cab3
CW
2115 'recipients' => [['test-event@example.com']],
2116 ],
2117 [
d3eae6ea
TO
2118 // After 2 months and 4 week
2119 'time' => '2012-09-13 02:00:00',
9099cab3
CW
2120 'recipients' => [['test-event@example.com']],
2121 ],
2122 [
d3eae6ea
TO
2123 // After 2 months and 6 weeks
2124 'time' => '2012-09-27 01:00:00',
9099cab3
CW
2125 'recipients' => [],
2126 ],
2127 ]);
d3eae6ea
TO
2128 }
2129
6a488035
TO
2130 // TODO // function testMembershipEndDate_NonMatch() { }
2131 // TODO // function testEventTypeStartDate_Match() { }
2132 // TODO // function testEventTypeEndDate_Match() { }
2133 // TODO // function testEventNameStartDate_Match() { }
2134 // TODO // function testEventNameEndDate_Match() { }
2135
2136 /**
92c99a4a 2137 * Run a series of cron jobs and make an assertion about email deliveries.
6a488035 2138 *
16b10e64
CW
2139 * @param array $cronRuns
2140 * array specifying when to run cron and what messages to expect; each item is an array with keys:
2141 * - time: string, e.g. '2012-06-15 21:00:01'
2142 * - recipients: array(array(string)), list of email addresses which should receive messages
6a488035 2143 */
00be9182 2144 public function assertCronRuns($cronRuns) {
6a488035
TO
2145 foreach ($cronRuns as $cronRun) {
2146 CRM_Utils_Time::setTime($cronRun['time']);
9099cab3 2147 $this->callAPISuccess('job', 'send_reminder', []);
6a488035 2148 $this->mut->assertRecipients($cronRun['recipients']);
f8c3594b
TO
2149 if (array_key_exists('subjects', $cronRun)) {
2150 $this->mut->assertSubjects($cronRun['subjects']);
2151 }
6a488035
TO
2152 $this->mut->clearMessages();
2153 }
2154 }
2155
6a488035 2156 /**
1d3260ea
SL
2157 * @var array
2158 * (DAO_Name => array(int)) List of items to garbage-collect during tearDown
6a488035
TO
2159 */
2160 private $_testObjects;
2161
2162 /**
2163 * Sets up the fixture, for example, opens a network connection.
92c99a4a 2164 *
6a488035 2165 * This method is called before a test is executed.
6a488035
TO
2166 */
2167 protected function _setUp() {
9099cab3 2168 $this->_testObjects = [];
6a488035
TO
2169 }
2170
2171 /**
2172 * Tears down the fixture, for example, closes a network connection.
92c99a4a 2173 *
6a488035 2174 * This method is called after a test is executed.
6a488035
TO
2175 */
2176 protected function _tearDown() {
2177 parent::tearDown();
2178 $this->deleteTestObjects();
2179 }
2180
2181 /**
2182 * This is a wrapper for CRM_Core_DAO::createTestObject which tracks
92c99a4a 2183 * created entities and provides for brainless cleanup.
6a488035
TO
2184 *
2185 * @see CRM_Core_DAO::createTestObject
92c99a4a 2186 *
1e1fdcf6
EM
2187 * @param $daoName
2188 * @param array $params
2189 * @param int $numObjects
2190 * @param bool $createOnly
92c99a4a
EM
2191 *
2192 * @return array|NULL|object
6a488035 2193 */
9099cab3 2194 public function createTestObject($daoName, $params = [], $numObjects = 1, $createOnly = FALSE) {
6a488035
TO
2195 $objects = CRM_Core_DAO::createTestObject($daoName, $params, $numObjects, $createOnly);
2196 if (is_array($objects)) {
2197 $this->registerTestObjects($objects);
0db6c3e1
TO
2198 }
2199 else {
9099cab3 2200 $this->registerTestObjects([$objects]);
6a488035
TO
2201 }
2202 return $objects;
2203 }
2204
2205 /**
5a4f6742
CW
2206 * @param array $objects
2207 * DAO or BAO objects.
6a488035 2208 */
00be9182 2209 public function registerTestObjects($objects) {
6a488035
TO
2210 //if (is_object($objects)) {
2211 // $objects = array($objects);
2212 //}
2213 foreach ($objects as $object) {
2214 $daoName = preg_replace('/_BAO_/', '_DAO_', get_class($object));
2215 $this->_testObjects[$daoName][] = $object->id;
2216 }
2217 }
2218
00be9182 2219 public function deleteTestObjects() {
6a488035
TO
2220 // Note: You might argue that the FK relations between test
2221 // objects could make this problematic; however, it should
2222 // behave intuitively as long as we mentally split our
2223 // test-objects between the "manual/primary records"
2224 // and the "automatic/secondary records"
2225 foreach ($this->_testObjects as $daoName => $daoIds) {
2226 foreach ($daoIds as $daoId) {
9099cab3 2227 CRM_Core_DAO::deleteTestObjects($daoName, ['id' => $daoId]);
6a488035
TO
2228 }
2229 }
9099cab3 2230 $this->_testObjects = [];
6a488035
TO
2231 }
2232
52f09320
PH
2233 /**
2234 * Test that the various repetition units work correctly.
2235 * CRM-17028
2236 */
2237 public function testRepetitionFrequencyUnit() {
9099cab3 2238 $membershipTypeParams = [
52f09320
PH
2239 'duration_interval' => '1',
2240 'duration_unit' => 'year',
2241 'is_active' => 1,
2242 'period_type' => 'rolling',
9099cab3 2243 ];
52f09320 2244 $membershipType = $this->createTestObject('CRM_Member_DAO_MembershipType', $membershipTypeParams);
9099cab3 2245 $interval_units = ['hour', 'day', 'week', 'month', 'year'];
52f09320
PH
2246 foreach ($interval_units as $interval_unit) {
2247 $membershipEndDate = DateTime::createFromFormat('Y-m-d H:i:s', "2013-03-15 00:00:00");
9099cab3 2248 $contactParams = [
52f09320
PH
2249 'contact_type' => 'Individual',
2250 'first_name' => 'Test',
2251 'last_name' => "Interval $interval_unit",
2252 'is_deceased' => 0,
9099cab3 2253 ];
52f09320
PH
2254 $contact = $this->createTestObject('CRM_Contact_DAO_Contact', $contactParams);
2255 $this->assertTrue(is_numeric($contact->id));
9099cab3 2256 $emailParams = [
52f09320 2257 'contact_id' => $contact->id,
62ca07e7 2258 'is_primary' => 1,
52f09320
PH
2259 'email' => "test-member-{$interval_unit}@example.com",
2260 'location_type_id' => 1,
9099cab3 2261 ];
52f09320
PH
2262 $email = $this->createTestObject('CRM_Core_DAO_Email', $emailParams);
2263 $this->assertTrue(is_numeric($email->id));
9099cab3 2264 $membershipParams = [
52f09320
PH
2265 'membership_type_id' => $membershipType->id,
2266 'contact_id' => $contact->id,
2267 'join_date' => '20120315',
2268 'start_date' => '20120315',
2269 'end_date' => '20130315',
2270 'is_override' => 0,
2271 'status_id' => 2,
9099cab3 2272 ];
52f09320
PH
2273 $membershipParams['status-id'] = 1;
2274 $membership = $this->createTestObject('CRM_Member_DAO_Membership', $membershipParams);
2275 $actionScheduleParams = $this->fixtures['sched_on_membership_end_date_repeat_interval'];
2276 $actionScheduleParams['entity_value'] = $membershipType->id;
2277 $actionScheduleParams['repetition_frequency_unit'] = $interval_unit;
2278 $actionScheduleParams['repetition_frequency_interval'] = 2;
2279 $actionSchedule = CRM_Core_BAO_ActionSchedule::add($actionScheduleParams);
2280 $this->assertTrue(is_numeric($actionSchedule->id));
2281 $beforeEndDate = $this->createModifiedDateTime($membershipEndDate, '-1 day');
2282 $beforeFirstUnit = $this->createModifiedDateTime($membershipEndDate, "+1 $interval_unit");
2283 $afterFirstUnit = $this->createModifiedDateTime($membershipEndDate, "+2 $interval_unit");
9099cab3
CW
2284 $cronRuns = [
2285 [
52f09320 2286 'time' => $beforeEndDate->format('Y-m-d H:i:s'),
9099cab3
CW
2287 'recipients' => [],
2288 ],
2289 [
52f09320 2290 'time' => $membershipEndDate->format('Y-m-d H:i:s'),
9099cab3
CW
2291 'recipients' => [["test-member-{$interval_unit}@example.com"]],
2292 ],
2293 [
52f09320 2294 'time' => $beforeFirstUnit->format('Y-m-d H:i:s'),
9099cab3
CW
2295 'recipients' => [],
2296 ],
2297 [
52f09320 2298 'time' => $afterFirstUnit->format('Y-m-d H:i:s'),
9099cab3
CW
2299 'recipients' => [["test-member-{$interval_unit}@example.com"]],
2300 ],
2301 ];
52f09320
PH
2302 $this->assertCronRuns($cronRuns);
2303 $actionSchedule->delete();
2304 $membership->delete();
2305 }
2306 }
2307
bb3ba83e
AH
2308 /**
2309 * Inherited members without permission to edit the main member contact should
2310 * not get reminders.
2311 *
2312 * However, just because a contact inherits one membership doesn't mean
2313 * reminders for other memberships should be suppressed.
2314 *
2315 * See CRM-14098
2316 */
2317 public function testInheritedMembershipPermissions() {
2318 // Set up common parameters for memberships.
2319 $membershipParams = $this->fixtures['rolling_membership'];
2320 $membershipParams['status_id'] = 1;
2321
2322 $membershipParams['membership_type_id']['relationship_type_id'] = 1;
2323 $membershipParams['membership_type_id']['relationship_direction'] = 'b_a';
2324 $membershipType1 = $this->createTestObject('CRM_Member_DAO_MembershipType', $membershipParams['membership_type_id']);
2325
2326 // We'll create a new membership type that can be held at the same time as
2327 // the first one.
2328 $membershipParams['membership_type_id']['relationship_type_id'] = 'NULL';
2329 $membershipParams['membership_type_id']['relationship_direction'] = 'NULL';
2330 $membershipType2 = $this->createTestObject('CRM_Member_DAO_MembershipType', $membershipParams['membership_type_id']);
2331
2332 // Create the parent membership and contact
2333 $membershipParams['membership_type_id'] = $membershipType1->id;
2334 $mainMembership = $this->createTestObject('CRM_Member_DAO_Membership', $membershipParams);
2335
2336 $contactParams = [
2337 'contact_type' => 'Individual',
2338 'first_name' => 'Mom',
2339 'last_name' => 'Rel',
2340 'is_deceased' => 0,
2341 ];
2342 $this->createTestObject('CRM_Contact_DAO_Contact', array_merge($contactParams, ['id' => $mainMembership->contact_id]));
2343
2344 $emailParams = [
2345 'contact_id' => $mainMembership->contact_id,
2346 'email' => 'test-member@example.com',
2347 'location_type_id' => 1,
2348 'is_primary' => 1,
2349 ];
2350 $email = $this->createTestObject('CRM_Core_DAO_Email', $emailParams);
2351
2352 // Set up contacts and emails for the two children
2353 $contactParams['first_name'] = 'Favorite';
2354 $permChild = $this->createTestObject('CRM_Contact_DAO_Contact', $contactParams);
2355 $emailParams['email'] = 'favorite@example.com';
2356 $emailParams['contact_id'] = $permChild->id;
2357 $this->createTestObject('CRM_Core_DAO_Email', $emailParams);
2358
2359 $contactParams['first_name'] = 'Black Sheep';
2360 $nonPermChild = $this->createTestObject('CRM_Contact_DAO_Contact', $contactParams);
2361 $emailParams['email'] = 'black.sheep@example.com';
2362 $emailParams['contact_id'] = $nonPermChild->id;
2363 $this->createTestObject('CRM_Core_DAO_Email', $emailParams);
2364
2365 // Each child gets a relationship, one with permission to edit the parent. This
2366 // will trigger inherited memberships for the first membership type
2367 $relParams = [
2368 'relationship_type_id' => 1,
2369 'contact_id_a' => $nonPermChild->id,
2370 'contact_id_b' => $mainMembership->contact_id,
2371 'is_active' => 1,
2372 ];
2373 $this->callAPISuccess('relationship', 'create', $relParams);
2374
2375 $relParams['contact_id_a'] = $permChild->id;
2376 $relParams['is_permission_a_b'] = CRM_Contact_BAO_Relationship::EDIT;
2377 $this->callAPISuccess('relationship', 'create', $relParams);
2378
2379 // Mom and Black Sheep get their own memberships of the second type.
2380 $membershipParams['membership_type_id'] = $membershipType2->id;
2381 $membershipParams['owner_membership_id'] = 'NULL';
2382 $membershipParams['contact_id'] = $mainMembership->contact_id;
2383 $this->createTestObject('CRM_Member_DAO_Membership', $membershipParams);
2384
2385 $membershipParams['contact_id'] = $nonPermChild->id;
2386 $this->createTestObject('CRM_Member_DAO_Membership', $membershipParams);
2387
2388 // Test a reminder for the first membership type - that should exclude Black
2389 // Sheep.
2390 $actionSchedule = $this->fixtures['sched_membership_join_2week'];
2391 $actionSchedule['entity_value'] = $membershipType1->id;
2392 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
2393 $this->assertTrue(is_numeric($actionScheduleDao->id));
2394
2395 $this->assertCronRuns([
2396 [
2397 'time' => '2012-03-29 01:00:00',
2398 'recipients' => [['test-member@example.com'], ['favorite@example.com']],
2399 'subjects' => [
2400 'subject sched_membership_join_2week (joined March 15th, 2012)',
2401 'subject sched_membership_join_2week (joined March 15th, 2012)',
2402 ],
2403 ],
2404 ]);
2405
2406 // Test a reminder for the second membership type - that should include
2407 // Black Sheep.
2408 $actionSchedule = $this->fixtures['sched_membership_start_1week'];
2409 $actionSchedule['entity_value'] = $membershipType2->id;
2410 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
2411 $this->assertTrue(is_numeric($actionScheduleDao->id));
2412
2413 $this->assertCronRuns([
2414 [
2415 'time' => '2012-03-22 01:00:00',
2416 'recipients' => [['test-member@example.com'], ['black.sheep@example.com']],
2417 'subjects' => [
2418 'subject sched_membership_start_1week (joined March 15th, 2012)',
2419 'subject sched_membership_start_1week (joined March 15th, 2012)',
2420 ],
2421 ],
2422 ]);
2423 }
2424
52f09320
PH
2425 public function createModifiedDateTime($origDateTime, $modifyRule) {
2426 $newDateTime = clone($origDateTime);
2427 $newDateTime->modify($modifyRule);
2428 return $newDateTime;
2429 }
2430
e08fae02 2431 public function testMembershipScheduleWithAbsoluteDate() {
9099cab3 2432 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], ['status_id' => 1]));
e08fae02 2433 $this->assertTrue(is_numeric($membership->id));
9099cab3 2434 $result = $this->callAPISuccess('Email', 'create', [
e08fae02
PH
2435 'contact_id' => $membership->contact_id,
2436 'email' => 'test-member@example.com',
2437 'location_type_id' => 1,
2438 'is_primary' => 1,
9099cab3 2439 ]);
e08fae02 2440
9099cab3 2441 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], ['contact_id' => $membership->contact_id]));
e08fae02
PH
2442 $actionSchedule = $this->fixtures['sched_membership_absolute_date'];
2443 $actionSchedule['entity_value'] = $membership->membership_type_id;
2444 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
2445 $this->assertTrue(is_numeric($actionScheduleDao->id));
2446
9099cab3
CW
2447 $this->assertCronRuns([
2448 [
e08fae02
PH
2449 // Before the 24-hour mark, no email
2450 'time' => '2012-06-13 04:00:00',
9099cab3
CW
2451 'recipients' => [],
2452 'subjects' => [],
2453 ],
2454 [
e08fae02
PH
2455 // On absolute date set on 2012-06-14
2456 'time' => '2012-06-14 00:00:00',
9099cab3
CW
2457 'recipients' => [['test-member@example.com']],
2458 'subjects' => ['subject sched_membership_absolute_date'],
2459 ],
2460 [
e08fae02
PH
2461 // Run cron 4 hours later; first message already sent
2462 'time' => '2012-06-14 04:00:00',
9099cab3
CW
2463 'recipients' => [],
2464 'subjects' => [],
2465 ],
2466 ]);
e08fae02
PH
2467 }
2468
6a488035 2469}