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