Fix civicrm_country template file
[civicrm-core.git] / tests / phpunit / CRM / Core / BAO / ActionScheduleTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2016 |
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 headless
31 */
32 class CRM_Core_BAO_ActionScheduleTest extends CiviUnitTestCase {
33
34 /**
35 * @var CiviMailUtils
36 */
37 public $mut;
38
39 public function setUp() {
40 parent::setUp();
41
42 $this->mut = new CiviMailUtils($this, TRUE);
43
44 $this->fixtures['rolling_membership'] = array(
45 'membership_type_id' => array(
46 'period_type' => 'rolling',
47 'duration_unit' => 'month',
48 'duration_interval' => '3',
49 'is_active' => 1,
50 ),
51 'join_date' => '20120315',
52 'start_date' => '20120315',
53 'end_date' => '20120615',
54 'is_override' => 0,
55 );
56
57 $this->fixtures['rolling_membership_past'] = array(
58 'membership_type_id' => array(
59 'period_type' => 'rolling',
60 'duration_unit' => 'month',
61 'duration_interval' => '3',
62 'is_active' => 1,
63 ),
64 'join_date' => '20100310',
65 'start_date' => '20100310',
66 'end_date' => '20100610',
67 'is_override' => 'NULL',
68 );
69 $this->fixtures['participant'] = array(
70 'event_id' => array(
71 'is_active' => 1,
72 'is_template' => 0,
73 'title' => 'Example Event',
74 'start_date' => '20120315',
75 'end_date' => '20120615',
76 ),
77 'role_id' => '1', // Attendee.
78 'status_id' => '8', // No-show.
79 );
80
81 $this->fixtures['phonecall'] = array(
82 'status_id' => 1,
83 'activity_type_id' => 2,
84 'activity_date_time' => '20120615100000',
85 'is_current_revision' => 1,
86 'is_deleted' => 0,
87 );
88 $this->fixtures['contact'] = array(
89 'is_deceased' => 0,
90 'contact_type' => 'Individual',
91 'email' => 'test-member@example.com',
92 'gender_id' => 'Female',
93 );
94 $this->fixtures['contact_birthdate'] = array(
95 'is_deceased' => 0,
96 'contact_type' => 'Individual',
97 'email' => 'test-bday@example.com',
98 'birth_date' => '20050707',
99 );
100 $this->fixtures['sched_activity_1day'] = array(
101 'name' => 'One_Day_Phone_Call_Notice',
102 'title' => 'One Day Phone Call Notice',
103 'limit_to' => '1',
104 'absolute_date' => NULL,
105 'body_html' => '<p>1-Day (non-repeating)</p>',
106 'body_text' => '1-Day (non-repeating)',
107 'end_action' => NULL,
108 'end_date' => NULL,
109 'end_frequency_interval' => NULL,
110 'end_frequency_unit' => NULL,
111 'entity_status' => '1',
112 'entity_value' => '2',
113 'group_id' => NULL,
114 'is_active' => '1',
115 'is_repeat' => '0',
116 'mapping_id' => '1',
117 'msg_template_id' => NULL,
118 'recipient' => '2',
119 'recipient_listing' => NULL,
120 'recipient_manual' => NULL,
121 'record_activity' => NULL,
122 'repetition_frequency_interval' => NULL,
123 'repetition_frequency_unit' => NULL,
124 'start_action_condition' => 'before',
125 'start_action_date' => 'activity_date_time',
126 'start_action_offset' => '1',
127 'start_action_unit' => 'day',
128 'subject' => '1-Day (non-repeating) (about {activity.activity_type})',
129 );
130 $this->fixtures['sched_activity_1day_r'] = array(
131 'name' => 'One_Day_Phone_Call_Notice_R',
132 'title' => 'One Day Phone Call Notice R',
133 'limit_to' => 1,
134 'absolute_date' => NULL,
135 'body_html' => '<p>1-Day (repeating)</p>',
136 'body_text' => '1-Day (repeating)',
137 'end_action' => 'after',
138 'end_date' => 'activity_date_time',
139 'end_frequency_interval' => '2',
140 'end_frequency_unit' => 'day',
141 'entity_status' => '1',
142 'entity_value' => '2',
143 'group_id' => NULL,
144 'is_active' => '1',
145 'is_repeat' => '1',
146 'mapping_id' => '1',
147 'msg_template_id' => NULL,
148 'recipient' => '2',
149 'recipient_listing' => NULL,
150 'recipient_manual' => NULL,
151 'record_activity' => NULL,
152 'repetition_frequency_interval' => '6',
153 'repetition_frequency_unit' => 'hour',
154 'start_action_condition' => 'before',
155 'start_action_date' => 'activity_date_time',
156 'start_action_offset' => '1',
157 'start_action_unit' => 'day',
158 'subject' => '1-Day (repeating) (about {activity.activity_type})',
159 );
160 $this->fixtures['sched_membership_join_2week'] = array(
161 'name' => 'sched_membership_join_2week',
162 'title' => 'sched_membership_join_2week',
163 'absolute_date' => '',
164 'body_html' => '<p>body sched_membership_join_2week</p>',
165 'body_text' => 'body sched_membership_join_2week',
166 'end_action' => '',
167 'end_date' => '',
168 'end_frequency_interval' => '',
169 'end_frequency_unit' => '',
170 'entity_status' => '',
171 'entity_value' => '',
172 'group_id' => '',
173 'is_active' => 1,
174 'is_repeat' => '0',
175 'mapping_id' => 4,
176 'msg_template_id' => '',
177 'recipient' => '',
178 'recipient_listing' => '',
179 'recipient_manual' => '',
180 'record_activity' => 1,
181 'repetition_frequency_interval' => '',
182 'repetition_frequency_unit' => '',
183 'start_action_condition' => 'after',
184 'start_action_date' => 'membership_join_date',
185 'start_action_offset' => '2',
186 'start_action_unit' => 'week',
187 'subject' => 'subject sched_membership_join_2week (joined {membership.join_date})',
188 );
189 $this->fixtures['sched_membership_end_2week'] = array(
190 'name' => 'sched_membership_end_2week',
191 'title' => 'sched_membership_end_2week',
192 'absolute_date' => '',
193 'body_html' => '<p>body sched_membership_end_2week</p>',
194 'body_text' => 'body sched_membership_end_2week',
195 'end_action' => '',
196 'end_date' => '',
197 'end_frequency_interval' => '',
198 'end_frequency_unit' => '',
199 'entity_status' => '',
200 'entity_value' => '',
201 'group_id' => '',
202 'is_active' => 1,
203 'is_repeat' => '0',
204 'mapping_id' => 4,
205 'msg_template_id' => '',
206 'recipient' => '',
207 'recipient_listing' => '',
208 'recipient_manual' => '',
209 'record_activity' => 1,
210 'repetition_frequency_interval' => '',
211 'repetition_frequency_unit' => '',
212 'start_action_condition' => 'before',
213 'start_action_date' => 'membership_end_date',
214 'start_action_offset' => '2',
215 'start_action_unit' => 'week',
216 'subject' => 'subject sched_membership_end_2week',
217 );
218 $this->fixtures['sched_on_membership_end_date'] = array(
219 'name' => 'sched_on_membership_end_date',
220 'title' => 'sched_on_membership_end_date',
221 'body_html' => '<p>Your membership expired today</p>',
222 'body_text' => 'Your membership expired today',
223 'is_active' => 1,
224 'mapping_id' => 4,
225 'record_activity' => 1,
226 'start_action_condition' => 'after',
227 'start_action_date' => 'membership_end_date',
228 'start_action_offset' => '0',
229 'start_action_unit' => 'hour',
230 'subject' => 'subject send reminder on membership_end_date',
231 );
232 $this->fixtures['sched_after_1day_membership_end_date'] = array(
233 'name' => 'sched_after_1day_membership_end_date',
234 'title' => 'sched_after_1day_membership_end_date',
235 'body_html' => '<p>Your membership expired yesterday</p>',
236 'body_text' => 'Your membership expired yesterday',
237 'is_active' => 1,
238 'mapping_id' => 4,
239 'record_activity' => 1,
240 'start_action_condition' => 'after',
241 'start_action_date' => 'membership_end_date',
242 'start_action_offset' => '1',
243 'start_action_unit' => 'day',
244 'subject' => 'subject send reminder on membership_end_date',
245 );
246
247 $this->fixtures['sched_membership_end_2month'] = array(
248 'name' => 'sched_membership_end_2month',
249 'title' => 'sched_membership_end_2month',
250 'absolute_date' => '',
251 'body_html' => '<p>body sched_membership_end_2month</p>',
252 'body_text' => 'body sched_membership_end_2month',
253 'end_action' => '',
254 'end_date' => '',
255 'end_frequency_interval' => '',
256 'end_frequency_unit' => '',
257 'entity_status' => '',
258 'entity_value' => '',
259 'group_id' => '',
260 'is_active' => 1,
261 'is_repeat' => '0',
262 'mapping_id' => 4,
263 'msg_template_id' => '',
264 'recipient' => '',
265 'recipient_listing' => '',
266 'recipient_manual' => '',
267 'record_activity' => 1,
268 'repetition_frequency_interval' => '',
269 'repetition_frequency_unit' => '',
270 'start_action_condition' => 'after',
271 'start_action_date' => 'membership_end_date',
272 'start_action_offset' => '2',
273 'start_action_unit' => 'month',
274 'subject' => 'subject sched_membership_end_2month',
275 );
276
277 $this->fixtures['sched_contact_bday_yesterday'] = array(
278 'name' => 'sched_contact_bday_yesterday',
279 'title' => 'sched_contact_bday_yesterday',
280 'absolute_date' => '',
281 'body_html' => '<p>you look like you were born yesterday!</p>',
282 'body_text' => 'you look like you were born yesterday!',
283 'end_action' => '',
284 'end_date' => '',
285 'end_frequency_interval' => '',
286 'end_frequency_unit' => '',
287 'entity_status' => 1,
288 'entity_value' => 'birth_date',
289 'group_id' => '',
290 'is_active' => 1,
291 'is_repeat' => '0',
292 'mapping_id' => 6,
293 'msg_template_id' => '',
294 'recipient' => '',
295 'recipient_listing' => '',
296 'recipient_manual' => '',
297 'record_activity' => 1,
298 'repetition_frequency_interval' => '',
299 'repetition_frequency_unit' => '',
300 'start_action_condition' => 'after',
301 'start_action_date' => 'date_field',
302 'start_action_offset' => '1',
303 'start_action_unit' => 'day',
304 'subject' => 'subject sched_contact_bday_yesterday',
305 );
306
307 $this->fixtures['sched_contact_bday_anniv'] = array(
308 'name' => 'sched_contact_bday_anniv',
309 'title' => 'sched_contact_bday_anniv',
310 'absolute_date' => '',
311 'body_html' => '<p>happy birthday!</p>',
312 'body_text' => 'happy birthday!',
313 'end_action' => '',
314 'end_date' => '',
315 'end_frequency_interval' => '',
316 'end_frequency_unit' => '',
317 'entity_status' => 2,
318 'entity_value' => 'birth_date',
319 'group_id' => '',
320 'is_active' => 1,
321 'is_repeat' => '0',
322 'mapping_id' => 6,
323 'msg_template_id' => '',
324 'recipient' => '',
325 'recipient_listing' => '',
326 'recipient_manual' => '',
327 'record_activity' => 1,
328 'repetition_frequency_interval' => '',
329 'repetition_frequency_unit' => '',
330 'start_action_condition' => 'before',
331 'start_action_date' => 'date_field',
332 'start_action_offset' => '1',
333 'start_action_unit' => 'day',
334 'subject' => 'subject sched_contact_bday_anniv',
335 );
336
337 $this->fixtures['sched_contact_grad_tomorrow'] = array(
338 'name' => 'sched_contact_grad_tomorrow',
339 'title' => 'sched_contact_grad_tomorrow',
340 'absolute_date' => '',
341 'body_html' => '<p>congratulations on your graduation!</p>',
342 'body_text' => 'congratulations on your graduation!',
343 'end_action' => '',
344 'end_date' => '',
345 'end_frequency_interval' => '',
346 'end_frequency_unit' => '',
347 'entity_status' => 1,
348 'group_id' => '',
349 'is_active' => 1,
350 'is_repeat' => '0',
351 'mapping_id' => 6,
352 'msg_template_id' => '',
353 'recipient' => '',
354 'recipient_listing' => '',
355 'recipient_manual' => '',
356 'record_activity' => 1,
357 'repetition_frequency_interval' => '',
358 'repetition_frequency_unit' => '',
359 'start_action_condition' => 'before',
360 'start_action_date' => 'date_field',
361 'start_action_offset' => '1',
362 'start_action_unit' => 'day',
363 'subject' => 'subject sched_contact_grad_tomorrow',
364 );
365
366 $this->fixtures['sched_contact_grad_anniv'] = array(
367 'name' => 'sched_contact_grad_anniv',
368 'title' => 'sched_contact_grad_anniv',
369 'absolute_date' => '',
370 'body_html' => '<p>dear alum, please send us money.</p>',
371 'body_text' => 'dear alum, please send us money.',
372 'end_action' => '',
373 'end_date' => '',
374 'end_frequency_interval' => '',
375 'end_frequency_unit' => '',
376 'entity_status' => 2,
377 'group_id' => '',
378 'is_active' => 1,
379 'is_repeat' => '0',
380 'mapping_id' => 6,
381 'msg_template_id' => '',
382 'recipient' => '',
383 'recipient_listing' => '',
384 'recipient_manual' => '',
385 'record_activity' => 1,
386 'repetition_frequency_interval' => '',
387 'repetition_frequency_unit' => '',
388 'start_action_condition' => 'after',
389 'start_action_date' => 'date_field',
390 'start_action_offset' => '1',
391 'start_action_unit' => 'week',
392 'subject' => 'subject sched_contact_grad_anniv',
393 );
394
395 $this->fixtures['sched_contact_created_yesterday'] = array(
396 'name' => 'sched_contact_created_yesterday',
397 'title' => 'sched_contact_created_yesterday',
398 'absolute_date' => '',
399 'body_html' => '<p>Your contact was created yesterday</p>',
400 'body_text' => 'Your contact was created yesterday!',
401 'end_action' => '',
402 'end_date' => '',
403 'end_frequency_interval' => '',
404 'end_frequency_unit' => '',
405 'entity_status' => 1,
406 'entity_value' => 'created_date',
407 'group_id' => '',
408 'is_active' => 1,
409 'is_repeat' => '0',
410 'mapping_id' => 6,
411 'msg_template_id' => '',
412 'recipient' => '',
413 'recipient_listing' => '',
414 'recipient_manual' => '',
415 'record_activity' => 1,
416 'repetition_frequency_interval' => '',
417 'repetition_frequency_unit' => '',
418 'start_action_condition' => 'after',
419 'start_action_date' => 'date_field',
420 'start_action_offset' => '1',
421 'start_action_unit' => 'day',
422 'subject' => 'subject sched_contact_created_yesterday',
423 );
424
425 $this->fixtures['sched_contact_mod_anniv'] = array(
426 'name' => 'sched_contact_mod_anniv',
427 'title' => 'sched_contact_mod_anniv',
428 'absolute_date' => '',
429 'body_html' => '<p>You last updated your data last year</p>',
430 'body_text' => 'Go update your stuff!',
431 'end_action' => '',
432 'end_date' => '',
433 'end_frequency_interval' => '',
434 'end_frequency_unit' => '',
435 'entity_status' => 2,
436 'entity_value' => 'modified_date',
437 'group_id' => '',
438 'is_active' => 1,
439 'is_repeat' => '0',
440 'mapping_id' => 6,
441 'msg_template_id' => '',
442 'recipient' => '',
443 'recipient_listing' => '',
444 'recipient_manual' => '',
445 'record_activity' => 1,
446 'repetition_frequency_interval' => '',
447 'repetition_frequency_unit' => '',
448 'start_action_condition' => 'before',
449 'start_action_date' => 'date_field',
450 'start_action_offset' => '1',
451 'start_action_unit' => 'day',
452 'subject' => 'subject sched_contact_mod_anniv',
453 );
454
455 $this->fixtures['sched_eventtype_start_1week_before'] = array(
456 'name' => 'sched_eventtype_start_1week_before',
457 'title' => 'sched_eventtype_start_1week_before',
458 'absolute_date' => '',
459 'body_html' => '<p>body sched_eventtype_start_1week_before ({event.title})</p>',
460 'body_text' => 'body sched_eventtype_start_1week_before ({event.title})',
461 'end_action' => '',
462 'end_date' => '',
463 'end_frequency_interval' => '',
464 'end_frequency_unit' => '',
465 'entity_status' => '', // participant status id
466 'entity_value' => '', // event type id
467 'group_id' => '',
468 'is_active' => 1,
469 'is_repeat' => '0',
470 'mapping_id' => 2, // event type
471 'msg_template_id' => '',
472 'recipient' => '',
473 'recipient_listing' => '',
474 'recipient_manual' => '',
475 'record_activity' => 1,
476 'repetition_frequency_interval' => '',
477 'repetition_frequency_unit' => '',
478 'start_action_condition' => 'before',
479 'start_action_date' => 'event_start_date',
480 'start_action_offset' => '1',
481 'start_action_unit' => 'week',
482 'subject' => 'subject sched_eventtype_start_1week_before ({event.title})',
483 );
484 $this->fixtures['sched_eventtype_end_2month_repeat_twice_2_weeks'] = array(
485 'name' => 'sched_eventtype_end_2month_repeat_twice_2_weeks',
486 'title' => 'sched_eventtype_end_2month_repeat_twice_2_weeks',
487 'absolute_date' => '',
488 'body_html' => '<p>body sched_eventtype_end_2month_repeat_twice_2_weeks {event.title}</p>',
489 'body_text' => 'body sched_eventtype_end_2month_repeat_twice_2_weeks {event.title}',
490 'end_action' => 'after',
491 'end_date' => 'event_end_date',
492 'end_frequency_interval' => '3',
493 'end_frequency_unit' => 'month',
494 'entity_status' => '', // participant status id
495 'entity_value' => '', // event type id
496 'group_id' => '',
497 'is_active' => 1,
498 'is_repeat' => '1',
499 'mapping_id' => 2, // event type
500 'msg_template_id' => '',
501 'recipient' => '',
502 'recipient_listing' => '',
503 'recipient_manual' => '',
504 'record_activity' => 1,
505 'repetition_frequency_interval' => '2',
506 'repetition_frequency_unit' => 'week',
507 'start_action_condition' => 'after',
508 'start_action_date' => 'event_end_date',
509 'start_action_offset' => '2',
510 'start_action_unit' => 'month',
511 'subject' => 'subject sched_eventtype_end_2month_repeat_twice_2_weeks {event.title}',
512 );
513
514 $this->fixtures['sched_membership_end_2month_repeat_twice_4_weeks'] = array(
515 'name' => 'sched_membership_end_2month',
516 'title' => 'sched_membership_end_2month',
517 'absolute_date' => '',
518 'body_html' => '<p>body sched_membership_end_2month</p>',
519 'body_text' => 'body sched_membership_end_2month',
520 'end_action' => '',
521 'end_date' => 'membership_end_date',
522 'end_frequency_interval' => '4',
523 'end_frequency_unit' => 'month',
524 'entity_status' => '',
525 'entity_value' => '',
526 'group_id' => '',
527 'is_active' => 1,
528 'is_repeat' => '1',
529 'mapping_id' => 4,
530 'msg_template_id' => '',
531 'recipient' => '',
532 'recipient_listing' => '',
533 'recipient_manual' => '',
534 'record_activity' => 1,
535 'repetition_frequency_interval' => '4',
536 'repetition_frequency_unit' => 'week',
537 'start_action_condition' => 'after',
538 'start_action_date' => 'membership_end_date',
539 'start_action_offset' => '2',
540 'start_action_unit' => 'month',
541 'subject' => 'subject sched_membership_end_2month',
542 );
543 $this->fixtures['sched_membership_end_limit_to_none'] = array(
544 'name' => 'limit to none',
545 'title' => 'limit to none',
546 'absolute_date' => '',
547 'body_html' => '<p>body sched_membership_end_2month</p>',
548 'body_text' => 'body sched_membership_end_2month',
549 'end_action' => '',
550 'end_date' => '',
551 'end_frequency_interval' => '4',
552 'end_frequency_unit' => 'month',
553 'entity_status' => '',
554 'entity_value' => '',
555 'limit_to' => 0,
556 'group_id' => '',
557 'is_active' => 1,
558 'is_repeat' => '1',
559 'mapping_id' => 4,
560 'msg_template_id' => '',
561 'recipient' => '',
562 'recipient_listing' => '',
563 'recipient_manual' => '',
564 'record_activity' => 1,
565 'repetition_frequency_interval' => '4',
566 'repetition_frequency_unit' => 'week',
567 'start_action_condition' => 'after',
568 'start_action_date' => 'membership_end_date',
569 'start_action_offset' => '2',
570 'start_action_unit' => 'month',
571 'subject' => 'limit to none',
572 );
573 $this->fixtures['sched_on_membership_end_date_repeat_interval'] = array(
574 'name' => 'sched_on_membership_end_date',
575 'title' => 'sched_on_membership_end_date',
576 'body_html' => '<p>Your membership expired 1 unit ago</p>',
577 'body_text' => 'Your membership expired 1 unit ago',
578 'end_frequency_interval' => 10,
579 'end_frequency_unit' => 'year',
580 'is_active' => 1,
581 'is_repeat' => TRUE,
582 'mapping_id' => 4,
583 'record_activity' => 1,
584 'start_action_condition' => 'after',
585 'start_action_date' => 'membership_end_date',
586 'start_action_offset' => '0',
587 'start_action_unit' => 'hour',
588 'subject' => 'subject send reminder every unit after membership_end_date',
589 );
590
591 $this->_setUp();
592 }
593
594 /**
595 * Tears down the fixture, for example, closes a network connection.
596 *
597 * This method is called after a test is executed.
598 */
599 public function tearDown() {
600 parent::tearDown();
601
602 $this->mut->clearMessages();
603 $this->mut->stop();
604 unset($this->mut);
605 $this->quickCleanup(array(
606 'civicrm_action_schedule',
607 'civicrm_action_log',
608 'civicrm_membership',
609 'civicrm_participant',
610 'civicrm_event',
611 'civicrm_email',
612 ));
613 $this->_tearDown();
614 }
615
616 public function mailerExamples() {
617 $cases = array();
618
619 $manyTokensTmpl = implode(';;', array(
620 '{contact.display_name}', // basic contact token
621 '{contact.gender}', // funny legacy contact token
622 '{contact.gender_id}', // funny legacy contact token
623 '{domain.name}', // domain token
624 '{activity.activity_type}', // action-scheduler token
625 ));
626 // Note: The behavior of domain-tokens on a scheduled reminder is undefined. All we
627 // can really do is check that it has something.
628 $manyTokensExpected = 'test-member@example.com;;Female;;Female;;[a-zA-Z0-9 ]+;;Phone Call';
629
630 // In this example, we use a lot of tokens cutting across multiple components..
631 $cases[0] = array(
632 // Schedule definition.
633 array(
634 'subject' => "subj $manyTokensTmpl",
635 'body_html' => "html $manyTokensTmpl",
636 'body_text' => "text $manyTokensTmpl",
637 ),
638 // Assertions (regex).
639 array(
640 'from_name' => "/^FIXME\$/",
641 'from_email' => "/^info@EXAMPLE.ORG\$/",
642 'subject' => "/^subj $manyTokensExpected\$/",
643 'body_html' => "/^html $manyTokensExpected\$/",
644 'body_text' => "/^text $manyTokensExpected\$/",
645 ),
646 );
647
648 // In this example, we customize the from address.
649 $cases[1] = array(
650 // Schedule definition.
651 array(
652 'from_name' => 'Bob',
653 'from_email' => 'bob@example.org',
654 ),
655 // Assertions (regex).
656 array(
657 'from_name' => "/^Bob\$/",
658 'from_email' => "/^bob@example.org\$/",
659 ),
660 );
661
662 // In this example, we autoconvert HTML to text
663 $cases[2] = array(
664 // Schedule definition.
665 array(
666 'body_html' => '<p>Hello &amp; stuff.</p>',
667 'body_text' => '',
668 ),
669 // Assertions (regex).
670 array(
671 'body_html' => '/^' . preg_quote('<p>Hello &amp; stuff.</p>', '/') . '/',
672 'body_text' => '/^' . preg_quote('Hello & stuff.', '/') . '/',
673 ),
674 );
675
676 // In this example, we autoconvert HTML to text
677 $cases[3] = array(
678 // Schedule definition.
679 array(
680 'body_html' => '',
681 'body_text' => 'Hello world',
682 ),
683 // Assertions (regex).
684 array(
685 'body_html' => '/^--UNDEFINED--$/',
686 'body_text' => '/^Hello world$/',
687 ),
688 );
689
690 return $cases;
691 }
692
693 /**
694 * This generates a single mailing through the scheduled-reminder
695 * system (using an activity-reminder as a baseline) and
696 * checks that the resulting message satisfies various
697 * regular expressions.
698 *
699 * @param array $schedule
700 * Values to set/override in the schedule.
701 * Ex: array('subject' => 'Hello, {contact.first_name}!').
702 * @param array $patterns
703 * A list of regexes to compare with the actual email.
704 * Ex: array('subject' => '/^Hello, Alice!/').
705 * Keys: subject, body_text, body_html, from_name, from_email.
706 * @dataProvider mailerExamples
707 */
708 public function testMailer($schedule, $patterns) {
709 $actionSchedule = array_merge($this->fixtures['sched_activity_1day'], $schedule);
710 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
711 $this->assertTrue(is_numeric($actionScheduleDao->id));
712
713 $activity = $this->createTestObject('CRM_Activity_DAO_Activity', $this->fixtures['phonecall']);
714 $this->assertTrue(is_numeric($activity->id));
715 $contact = $this->callAPISuccess('contact', 'create', $this->fixtures['contact']);
716 $activity->save();
717
718 $source['contact_id'] = $contact['id'];
719 $source['activity_id'] = $activity->id;
720 $source['record_type_id'] = 2;
721 $activityContact = $this->createTestObject('CRM_Activity_DAO_ActivityContact', $source);
722 $activityContact->save();
723
724 CRM_Utils_Time::setTime('2012-06-14 15:00:00');
725 $this->callAPISuccess('job', 'send_reminder', array());
726 $this->mut->assertRecipients(array(array('test-member@example.com')));
727 foreach ($this->mut->getAllMessages('ezc') as $message) {
728 /** @var ezcMail $message */
729
730 $messageArray = array();
731 $messageArray['subject'] = $message->subject;
732 $messageArray['from_name'] = $message->from->name;
733 $messageArray['from_email'] = $message->from->email;
734 $messageArray['body_text'] = '--UNDEFINED--';
735 $messageArray['body_html'] = '--UNDEFINED--';
736
737 foreach ($message->fetchParts() as $part) {
738 /** @var ezcMailText ezcMailText */
739 if ($part instanceof ezcMailText && $part->subType == 'html') {
740 $messageArray['body_html'] = $part->text;
741 }
742 if ($part instanceof ezcMailText && $part->subType == 'plain') {
743 $messageArray['body_text'] = $part->text;
744 }
745 }
746
747 foreach ($patterns as $field => $pattern) {
748 $this->assertRegExp($pattern, $messageArray[$field],
749 "Check that '$field'' matches regex. " . print_r(array('expected' => $patterns, 'actual' => $messageArray), 1));
750 }
751 }
752 $this->mut->clearMessages();
753
754 }
755
756 public function testActivityDateTimeMatchNonRepeatableSchedule() {
757 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($this->fixtures['sched_activity_1day']);
758 $this->assertTrue(is_numeric($actionScheduleDao->id));
759
760 $activity = $this->createTestObject('CRM_Activity_DAO_Activity', $this->fixtures['phonecall']);
761 $this->assertTrue(is_numeric($activity->id));
762 $contact = $this->callAPISuccess('contact', 'create', $this->fixtures['contact']);
763 $activity->save();
764
765 $source['contact_id'] = $contact['id'];
766 $source['activity_id'] = $activity->id;
767 $source['record_type_id'] = 2;
768 $activityContact = $this->createTestObject('CRM_Activity_DAO_ActivityContact', $source);
769 $activityContact->save();
770
771 $this->assertCronRuns(array(
772 array(
773 // Before the 24-hour mark, no email
774 'time' => '2012-06-14 04:00:00',
775 'recipients' => array(),
776 'subjects' => array(),
777 ),
778 array(
779 // After the 24-hour mark, an email
780 'time' => '2012-06-14 15:00:00',
781 'recipients' => array(array('test-member@example.com')),
782 'subjects' => array('1-Day (non-repeating) (about Phone Call)'),
783 ),
784 array(
785 // Run cron again; message already sent
786 'time' => '',
787 'recipients' => array(),
788 ),
789 ));
790 }
791
792 public function testActivityDateTimeMatchRepeatableSchedule() {
793 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($this->fixtures['sched_activity_1day_r']);
794 $this->assertTrue(is_numeric($actionScheduleDao->id));
795
796 $activity = $this->createTestObject('CRM_Activity_DAO_Activity', $this->fixtures['phonecall']);
797 $this->assertTrue(is_numeric($activity->id));
798 $contact = $this->callAPISuccess('contact', 'create', $this->fixtures['contact']);
799 $activity->save();
800
801 $source['contact_id'] = $contact['id'];
802 $source['activity_id'] = $activity->id;
803 $source['record_type_id'] = 2;
804 $activityContact = $this->createTestObject('CRM_Activity_DAO_ActivityContact', $source);
805 $activityContact->save();
806
807 $this->assertCronRuns(array(
808 array(
809 // Before the 24-hour mark, no email
810 'time' => '012-06-14 04:00:00',
811 'recipients' => array(),
812 'subjects' => array(),
813 ),
814 array(
815 // After the 24-hour mark, an email
816 'time' => '2012-06-14 15:00:00',
817 'recipients' => array(array('test-member@example.com')),
818 'subjects' => array('1-Day (repeating) (about Phone Call)'),
819 ),
820 array(
821 // Run cron 4 hours later; first message already sent
822 'time' => '2012-06-14 20:00:00',
823 'recipients' => array(),
824 'subjects' => array(),
825 ),
826 array(
827 // Run cron 6 hours later; send second message.
828 'time' => '2012-06-14 21:00:01',
829 'recipients' => array(array('test-member@example.com')),
830 'subjects' => array('1-Day (repeating) (about Phone Call)'),
831 ),
832 ));
833 }
834
835 /**
836 * For contacts/activities which don't match the schedule filter,
837 * an email should *not* be sent.
838 */
839 // TODO // function testActivityDateTime_NonMatch() { }
840
841 /**
842 * For contacts/members which match schedule based on join date,
843 * an email should be sent.
844 */
845 public function testMembershipJoinDateMatch() {
846 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], array('status_id' => 1)));
847 $this->assertTrue(is_numeric($membership->id));
848 $result = $this->callAPISuccess('Email', 'create', array(
849 'contact_id' => $membership->contact_id,
850 'email' => 'test-member@example.com',
851 'location_type_id' => 1,
852 ));
853 $this->assertAPISuccess($result);
854
855 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], array('contact_id' => $membership->contact_id)));
856 $actionSchedule = $this->fixtures['sched_membership_join_2week'];
857 $actionSchedule['entity_value'] = $membership->membership_type_id;
858 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
859 $this->assertTrue(is_numeric($actionScheduleDao->id));
860
861 // start_date=2012-03-15 ; schedule is 2 weeks after start_date
862 $this->assertCronRuns(array(
863 array(
864 // Before the 2-week mark, no email.
865 'time' => '2012-03-28 01:00:00',
866 'recipients' => array(),
867 'subjects' => array(),
868 ),
869 array(
870 // After the 2-week mark, send an email.
871 'time' => '2012-03-29 01:00:00',
872 'recipients' => array(array('test-member@example.com')),
873 'subjects' => array('subject sched_membership_join_2week (joined March 15th, 2012)'),
874 ),
875 ));
876 }
877
878 /**
879 * Test end date email sent.
880 *
881 * For contacts/members which match schedule based on join date,
882 * an email should be sent.
883 */
884 public function testMembershipJoinDateNonMatch() {
885 $membership = $this->createTestObject('CRM_Member_DAO_Membership', $this->fixtures['rolling_membership']);
886 $this->assertTrue(is_numeric($membership->id));
887 $result = $this->callAPISuccess('Email', 'create', array(
888 'contact_id' => $membership->contact_id,
889 'location_type_id' => 1,
890 'email' => 'test-member@example.com',
891 ));
892
893 // Add an alternative membership type, and only send messages for that type
894 $extraMembershipType = $this->createTestObject('CRM_Member_DAO_MembershipType', array());
895 $this->assertTrue(is_numeric($extraMembershipType->id));
896 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($this->fixtures['sched_membership_join_2week']);
897 $this->assertTrue(is_numeric($actionScheduleDao->id));
898 $actionScheduleDao->entity_value = $extraMembershipType->id;
899 $actionScheduleDao->save();
900
901 // start_date=2012-03-15 ; schedule is 2 weeks after start_date
902 $this->assertCronRuns(array(
903 array(
904 // After the 2-week mark, don't send email because we have different membership type.
905 'time' => '2012-03-29 01:00:00',
906 'recipients' => array(),
907 ),
908 ));
909 }
910
911 /**
912 * Test that the first and SECOND notifications are sent out.
913 */
914 public function testMembershipEndDateRepeat() {
915 // creates membership with end_date = 20120615
916 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], array('status_id' => 2)));
917 $result = $this->callAPISuccess('Email', 'create', array(
918 'contact_id' => $membership->contact_id,
919 'email' => 'test-member@example.com',
920 ));
921 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], array('contact_id' => $membership->contact_id)));
922
923 $actionSchedule = $this->fixtures['sched_membership_end_2month_repeat_twice_4_weeks'];
924 $actionSchedule['entity_value'] = $membership->membership_type_id;
925 $this->callAPISuccess('action_schedule', 'create', $actionSchedule);
926
927 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
928 $this->assertCronRuns(array(
929 array(
930 // After the 2-week mark, send an email.
931 'time' => '2012-08-15 01:00:00',
932 'recipients' => array(array('test-member@example.com')),
933 ),
934 array(
935 // After the 2-week mark, send an email.
936 'time' => '2012-09-12 01:00:00',
937 'recipients' => array(array('test-member@example.com')),
938 ),
939 ));
940 }
941
942 /**
943 * Test behaviour when date changes.
944 *
945 * Test that the first notification is sent but the second is NOT sent if the end date changes in
946 * between
947 * see CRM-15376
948 */
949 public function testMembershipEndDateRepeatChangedEndDate_CRM_15376() {
950 // creates membership with end_date = 20120615
951 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], array('status_id' => 2)));
952 $this->callAPISuccess('Email', 'create', array(
953 'contact_id' => $membership->contact_id,
954 'email' => 'test-member@example.com',
955 ));
956 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], array('contact_id' => $membership->contact_id)));
957
958 $actionSchedule = $this->fixtures['sched_membership_end_2month_repeat_twice_4_weeks'];
959 $actionSchedule['entity_value'] = $membership->membership_type_id;
960 $this->callAPISuccess('action_schedule', 'create', $actionSchedule);
961 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
962 $this->assertCronRuns(array(
963 array(
964 // After the 2-week mark, send an email.
965 'time' => '2012-08-15 01:00:00',
966 'recipients' => array(array('test-member@example.com')),
967 ),
968 ));
969
970 // Extend membership - reminder should NOT go out.
971 $this->callAPISuccess('membership', 'create', array('id' => $membership->id, 'end_date' => '2014-01-01'));
972 $this->assertCronRuns(array(
973 array(
974 // After the 2-week mark, send an email.
975 'time' => '2012-09-12 01:00:00',
976 'recipients' => array(),
977 ),
978 ));
979 }
980
981 /**
982 * Test membership end date email sends.
983 *
984 * For contacts/members which match schedule based on end date,
985 * an email should be sent.
986 */
987 public function testMembershipEndDateMatch() {
988 // creates membership with end_date = 20120615
989 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], array('status_id' => 2)));
990 $this->assertTrue(is_numeric($membership->id));
991 $this->callAPISuccess('Email', 'create', array(
992 'contact_id' => $membership->contact_id,
993 'email' => 'test-member@example.com',
994 ));
995 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], array('contact_id' => $membership->contact_id)));
996
997 $actionSchedule = $this->fixtures['sched_membership_end_2week'];
998 $actionSchedule['entity_value'] = $membership->membership_type_id;
999 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
1000 $this->assertTrue(is_numeric($actionScheduleDao->id));
1001
1002 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
1003 $this->assertCronRuns(array(
1004 array(
1005 // Before the 2-week mark, no email.
1006 'time' => '2012-05-31 01:00:00',
1007 // 'time' => '2012-06-01 01:00:00',
1008 // FIXME: Is this the right boundary?
1009 'recipients' => array(),
1010 ),
1011 array(
1012 // After the 2-week mark, send an email.
1013 'time' => '2012-06-01 01:00:00',
1014 'recipients' => array(array('test-member@example.com')),
1015 ),
1016 ));
1017
1018 // Now suppose user has renewed for rolling membership after 3 months, so upcoming assertion is written
1019 // to ensure that new reminder is sent 2 week before the new end_date i.e. '2012-09-15'
1020 $membership->end_date = '2012-09-15';
1021 $membership->save();
1022
1023 //change the email id of chosen membership contact to assert
1024 //recipient of not the previously sent mail but the new one
1025 $result = $this->callAPISuccess('Email', 'create', array(
1026 'is_primary' => 1,
1027 'contact_id' => $membership->contact_id,
1028 'email' => 'member2@example.com',
1029 ));
1030 $this->assertAPISuccess($result);
1031
1032 // end_date=2012-09-15 ; schedule is 2 weeks before end_date
1033 $this->assertCronRuns(array(
1034 array(
1035 // Before the 2-week mark, no email
1036 'time' => '2012-08-31 01:00:00',
1037 'recipients' => array(),
1038 ),
1039 //array( // After the 2-week mark, send an email
1040 //'time' => '2012-09-01 01:00:00',
1041 //'recipients' => array(array('member2@example.com')),
1042 //),
1043 ));
1044 }
1045
1046
1047 /**
1048 * Test membership end date email.
1049 *
1050 * For contacts/members which match schedule based on end date,
1051 * an email should be sent.
1052 */
1053 public function testMembershipEndDateNoMatch() {
1054 // creates membership with end_date = 20120615
1055 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], array('status_id' => 3)));
1056 $this->assertTrue(is_numeric($membership->id));
1057 $result = $this->callAPISuccess('Email', 'create', array(
1058 'contact_id' => $membership->contact_id,
1059 'email' => 'test-member@example.com',
1060 ));
1061 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], array('contact_id' => $membership->contact_id)));
1062
1063 $actionSchedule = $this->fixtures['sched_membership_end_2month'];
1064 $actionSchedule['entity_value'] = $membership->membership_type_id;
1065 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
1066 $this->assertTrue(is_numeric($actionScheduleDao->id));
1067
1068 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
1069 $this->assertCronRuns(array(
1070 array(
1071 // Before the 2-week mark, no email.
1072 'time' => '2012-05-31 01:00:00',
1073 // 'time' => '2012-06-01 01:00:00',
1074 // FIXME: Is this the right boundary?
1075 'recipients' => array(),
1076 ),
1077 array(
1078 // After the 2-week mark, send an email.
1079 'time' => '2013-05-01 01:00:00',
1080 'recipients' => array(),
1081 ),
1082 ));
1083 }
1084
1085 public function testContactBirthDateNoAnniv() {
1086 $contact = $this->callAPISuccess('Contact', 'create', $this->fixtures['contact_birthdate']);
1087 $this->_testObjects['CRM_Contact_DAO_Contact'][] = $contact['id'];
1088 $actionSchedule = $this->fixtures['sched_contact_bday_yesterday'];
1089 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
1090 $this->assertTrue(is_numeric($actionScheduleDao->id));
1091 $this->assertCronRuns(array(
1092 array(
1093 // On the birthday, no email.
1094 'time' => '2005-07-07 01:00:00',
1095 'recipients' => array(),
1096 ),
1097 array(
1098 // The next day, send an email.
1099 'time' => '2005-07-08 20:00:00',
1100 'recipients' => array(array('test-bday@example.com')),
1101 ),
1102 ));
1103 }
1104
1105 public function testContactBirthDateAnniversary() {
1106 $contact = $this->callAPISuccess('Contact', 'create', $this->fixtures['contact_birthdate']);
1107 $this->_testObjects['CRM_Contact_DAO_Contact'][] = $contact['id'];
1108 $actionSchedule = $this->fixtures['sched_contact_bday_anniv'];
1109 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
1110 $this->assertTrue(is_numeric($actionScheduleDao->id));
1111 $this->assertCronRuns(array(
1112 array(
1113 // On some random day, no email.
1114 'time' => '2014-03-07 01:00:00',
1115 'recipients' => array(),
1116 ),
1117 array(
1118 // On the eve of their 9th birthday, send an email.
1119 'time' => '2014-07-06 20:00:00',
1120 'recipients' => array(array('test-bday@example.com')),
1121 ),
1122 ));
1123 }
1124
1125 public function testContactCustomDateNoAnniv() {
1126 $group = array(
1127 'title' => 'Test_Group',
1128 'name' => 'test_group',
1129 'extends' => array('Individual'),
1130 'style' => 'Inline',
1131 'is_multiple' => FALSE,
1132 'is_active' => 1,
1133 );
1134 $createGroup = $this->callAPISuccess('custom_group', 'create', $group);
1135 $field = array(
1136 'label' => 'Graduation',
1137 'data_type' => 'Date',
1138 'html_type' => 'Select Date',
1139 'custom_group_id' => $createGroup['id'],
1140 );
1141 $createField = $this->callAPISuccess('custom_field', 'create', $field);
1142 $contactParams = $this->fixtures['contact'];
1143 $contactParams["custom_{$createField['id']}"] = '2013-12-16';
1144 $contact = $this->callAPISuccess('Contact', 'create', $contactParams);
1145 $this->_testObjects['CRM_Contact_DAO_Contact'][] = $contact['id'];
1146 $actionSchedule = $this->fixtures['sched_contact_grad_tomorrow'];
1147 $actionSchedule['entity_value'] = "custom_{$createField['id']}";
1148 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
1149 $this->assertTrue(is_numeric($actionScheduleDao->id));
1150 $this->assertCronRuns(array(
1151 array(
1152 // On some random day, no email.
1153 'time' => '2014-03-07 01:00:00',
1154 'recipients' => array(),
1155 ),
1156 array(
1157 // On the eve of their graduation, send an email.
1158 'time' => '2013-12-15 20:00:00',
1159 'recipients' => array(array('test-member@example.com')),
1160 ),
1161 ));
1162 $this->callAPISuccess('custom_group', 'delete', array('id' => $createGroup['id']));
1163 }
1164
1165 public function testContactCreatedNoAnniv() {
1166 $contact = $this->callAPISuccess('Contact', 'create', $this->fixtures['contact_birthdate']);
1167 $this->_testObjects['CRM_Contact_DAO_Contact'][] = $contact['id'];
1168 $actionSchedule = $this->fixtures['sched_contact_created_yesterday'];
1169 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
1170 $this->assertTrue(is_numeric($actionScheduleDao->id));
1171 $this->assertCronRuns(array(
1172 array(
1173 // On the date created, no email.
1174 'time' => $contact['values'][$contact['id']]['created_date'],
1175 'recipients' => array(),
1176 ),
1177 array(
1178 // The next day, send an email.
1179 'time' => date('Y-m-d H:i:s', strtotime($contact['values'][$contact['id']]['created_date'] . ' +1 day')),
1180 'recipients' => array(array('test-bday@example.com')),
1181 ),
1182 ));
1183 }
1184
1185 public function testContactModifiedAnniversary() {
1186 $contact = $this->callAPISuccess('Contact', 'create', $this->fixtures['contact_birthdate']);
1187 $this->_testObjects['CRM_Contact_DAO_Contact'][] = $contact['id'];
1188 $modifiedDate = $this->callAPISuccess('Contact', 'getvalue', array('id' => $contact['id'], 'return' => 'modified_date'));
1189 $actionSchedule = $this->fixtures['sched_contact_mod_anniv'];
1190 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
1191 $this->assertTrue(is_numeric($actionScheduleDao->id));
1192 $this->assertCronRuns(array(
1193 array(
1194 // On some random day, no email.
1195 'time' => date('Y-m-d H:i:s', strtotime($contact['values'][$contact['id']]['modified_date'] . ' -60 days')),
1196 'recipients' => array(),
1197 ),
1198 array(
1199 // On the eve of 3 years after they were modified, send an email.
1200 'time' => date('Y-m-d H:i:s', strtotime($modifiedDate . ' +3 years -1 day')),
1201 'recipients' => array(array('test-bday@example.com')),
1202 ),
1203 ));
1204 }
1205
1206 /**
1207 * Check that limit_to + an empty recipients doesn't sent to multiple contacts.
1208 */
1209 public function testMembershipLimitToNone() {
1210 // creates membership with end_date = 20120615
1211 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], array('status_id' => 2)));
1212
1213 $this->assertTrue(is_numeric($membership->id));
1214 $result = $this->callAPISuccess('Email', 'create', array(
1215 'contact_id' => $membership->contact_id,
1216 'email' => 'member@example.com',
1217 ));
1218 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], array('contact_id' => $membership->contact_id)));
1219 $this->callAPISuccess('contact', 'create', array('email' => 'b@c.com', 'contact_type' => 'Individual'));
1220
1221 $this->assertAPISuccess($result);
1222
1223 $actionSchedule = $this->fixtures['sched_membership_end_limit_to_none'];
1224 $actionSchedule['entity_value'] = $membership->membership_type_id;
1225 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
1226 $this->assertTrue(is_numeric($actionScheduleDao->id));
1227
1228 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
1229 $this->assertCronRuns(array(
1230 array(
1231 // Before the 2-week mark, no email.
1232 'time' => '2012-05-31 01:00:00',
1233 // 'time' => '2012-06-01 01:00:00', // FIXME: Is this the right boundary?
1234 'recipients' => array(),
1235 ),
1236 ));
1237 }
1238
1239 public function testMembership_referenceDate() {
1240 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], array('status_id' => 2)));
1241
1242 $this->assertTrue(is_numeric($membership->id));
1243 $result = $this->callAPISuccess('Email', 'create', array(
1244 'contact_id' => $membership->contact_id,
1245 'email' => 'member@example.com',
1246 ));
1247
1248 $result = $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], array('contact_id' => $membership->contact_id)));
1249 $this->assertAPISuccess($result);
1250
1251 $actionSchedule = $this->fixtures['sched_membership_join_2week'];
1252 $actionSchedule['entity_value'] = $membership->membership_type_id;
1253 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
1254 $this->assertTrue(is_numeric($actionScheduleDao->id));
1255
1256 // start_date=2012-03-15 ; schedule is 2 weeks after start_date
1257 $this->assertCronRuns(array(
1258 array(
1259 // After the 2-week mark, send an email
1260 'time' => '2012-03-29 01:00:00',
1261 'recipients' => array(array('member@example.com')),
1262 ),
1263 array(
1264 // After the 2-week 1day mark, don't send an email
1265 'time' => '2012-03-30 01:00:00',
1266 'recipients' => array(),
1267 ),
1268 ));
1269
1270 //check if reference date is set to membership's join date
1271 //as per the action_start_date chosen for current schedule reminder
1272 $this->assertEquals('2012-03-15',
1273 CRM_Core_DAO::getFieldValue('CRM_Core_DAO_ActionLog', $membership->contact_id, 'reference_date', 'contact_id')
1274 );
1275
1276 //change current membership join date that may signifies as membership renewal activity
1277 $membership->join_date = '2012-03-29';
1278 $membership->save();
1279
1280 $this->assertCronRuns(array(
1281 array(
1282 // After the 13 days of the changed join date 2012-03-29, don't send an email
1283 'time' => '2012-04-11 01:00:00',
1284 'recipients' => array(),
1285 ),
1286 array(
1287 // After the 2-week of the changed join date 2012-03-29, send an email
1288 'time' => '2012-04-12 01:00:00',
1289 'recipients' => array(array('member@example.com')),
1290 ),
1291 ));
1292 $this->assertCronRuns(array(
1293 array(
1294 // It should not re-send on the same day
1295 'time' => '2012-04-12 01:00:00',
1296 'recipients' => array(),
1297 ),
1298 ));
1299 }
1300
1301 public function testMembershipOnMultipleReminder() {
1302 $membership = $this->createTestObject('CRM_Member_DAO_Membership', array_merge($this->fixtures['rolling_membership'], array('status_id' => 2)));
1303
1304 $this->assertTrue(is_numeric($membership->id));
1305 $result = $this->callAPISuccess('Email', 'create', array(
1306 'contact_id' => $membership->contact_id,
1307 'email' => 'member@example.com',
1308 ));
1309 $result = $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], array('contact_id' => $membership->contact_id)));
1310 $this->assertAPISuccess($result);
1311
1312 $actionScheduleBefore = $this->fixtures['sched_membership_end_2week']; // Send email 2 weeks before end_date
1313 $actionScheduleOn = $this->fixtures['sched_on_membership_end_date']; // Send email on end_date/expiry date
1314 $actionScheduleAfter = $this->fixtures['sched_after_1day_membership_end_date']; // Send email 1 day after end_date/grace period
1315 $actionScheduleBefore['entity_value'] = $actionScheduleOn['entity_value'] = $actionScheduleAfter['entity_value'] = $membership->membership_type_id;
1316 foreach (array('actionScheduleBefore', 'actionScheduleOn', 'actionScheduleAfter') as $value) {
1317 $$value = CRM_Core_BAO_ActionSchedule::add($$value);
1318 $this->assertTrue(is_numeric($$value->id));
1319 }
1320
1321 $this->assertCronRuns(
1322 array(
1323 array(
1324 // 1day 2weeks before membership end date(MED), don't send mail
1325 'time' => '2012-05-31 01:00:00',
1326 'recipients' => array(),
1327 ),
1328 array(
1329 // 2 weeks before MED, send an email
1330 'time' => '2012-06-01 01:00:00',
1331 'recipients' => array(array('member@example.com')),
1332 ),
1333 array(
1334 // 1day before MED, don't send mail
1335 'time' => '2012-06-14 01:00:00',
1336 'recipients' => array(),
1337 ),
1338 array(
1339 // On MED, send an email
1340 'time' => '2012-06-15 00:00:00',
1341 'recipients' => array(array('member@example.com')),
1342 ),
1343 array(
1344 // After 1day of MED, send an email
1345 'time' => '2012-06-16 01:00:00',
1346 'recipients' => array(array('member@example.com')),
1347 ),
1348 array(
1349 // After 1day 1min of MED, don't send an email
1350 'time' => '2012-06-17 00:01:00',
1351 'recipients' => array(),
1352 ),
1353 )
1354 );
1355
1356 // Assert the timestamp as of when the emails of respective three reminders as configured
1357 // 2 weeks before, on and 1 day after MED, are sent
1358 $this->assertApproxEquals(
1359 strtotime('2012-06-01 01:00:00'),
1360 strtotime(CRM_Core_DAO::getFieldValue('CRM_Core_DAO_ActionLog', $actionScheduleBefore->id, 'action_date_time', 'action_schedule_id', TRUE)),
1361 3 // Variation in test execution time.
1362 );
1363 $this->assertApproxEquals(
1364 strtotime('2012-06-15 00:00:00'),
1365 strtotime(CRM_Core_DAO::getFieldValue('CRM_Core_DAO_ActionLog', $actionScheduleOn->id, 'action_date_time', 'action_schedule_id', TRUE)),
1366 3 // Variation in test execution time.
1367 );
1368 $this->assertApproxEquals(
1369 strtotime('2012-06-16 01:00:00'),
1370 strtotime(CRM_Core_DAO::getFieldValue('CRM_Core_DAO_ActionLog', $actionScheduleAfter->id, 'action_date_time', 'action_schedule_id', TRUE)),
1371 3 // Variation in test execution time.
1372 );
1373
1374 //extend MED to 2 weeks after the current MED (that may signifies as membership renewal activity)
1375 // and lets assert as of when the new set of reminders will be sent against their respective Schedule Reminders(SR)
1376 $membership->end_date = '2012-06-20';
1377 $membership->save();
1378
1379 $result = $this->callAPISuccess('Contact', 'get', array('id' => $membership->contact_id));
1380 $this->assertCronRuns(
1381 array(
1382 array(
1383 // 1day 2weeks before membership end date(MED), don't send mail
1384 'time' => '2012-06-05 01:00:00',
1385 'recipients' => array(),
1386 ),
1387 array(
1388 // 2 weeks before MED, send an email
1389 'time' => '2012-06-06 01:00:00',
1390 'recipients' => array(array('member@example.com')),
1391 ),
1392 array(
1393 // 1day before MED, don't send mail
1394 'time' => '2012-06-19 01:00:00',
1395 'recipients' => array(),
1396 ),
1397 array(
1398 // On MED, send an email
1399 'time' => '2012-06-20 00:00:00',
1400 'recipients' => array(array('member@example.com')),
1401 ),
1402 array(
1403 // After 1day of MED, send an email
1404 'time' => '2012-06-21 01:00:00',
1405 'recipients' => array(array('member@example.com')),
1406 ),
1407 array(
1408 // After 1day 1min of MED, don't send an email
1409 'time' => '2012-07-21 00:01:00',
1410 'recipients' => array(),
1411 ),
1412 ));
1413 }
1414
1415 public function testContactCustomDate_Anniv() {
1416 $group = array(
1417 'title' => 'Test_Group now',
1418 'name' => 'test_group_now',
1419 'extends' => array('Individual'),
1420 'style' => 'Inline',
1421 'is_multiple' => FALSE,
1422 'is_active' => 1,
1423 );
1424 $createGroup = $this->callAPISuccess('custom_group', 'create', $group);
1425 $field = array(
1426 'label' => 'Graduation',
1427 'data_type' => 'Date',
1428 'html_type' => 'Select Date',
1429 'custom_group_id' => $createGroup['id'],
1430 );
1431 $createField = $this->callAPISuccess('custom_field', 'create', $field);
1432
1433 $contactParams = $this->fixtures['contact'];
1434 $contactParams["custom_{$createField['id']}"] = '2013-12-16';
1435 $contact = $this->callAPISuccess('Contact', 'create', $contactParams);
1436 $this->_testObjects['CRM_Contact_DAO_Contact'][] = $contact['id'];
1437 $actionSchedule = $this->fixtures['sched_contact_grad_anniv'];
1438 $actionSchedule['entity_value'] = "custom_{$createField['id']}";
1439 $actionScheduleDao = CRM_Core_BAO_ActionSchedule::add($actionSchedule);
1440 $this->assertTrue(is_numeric($actionScheduleDao->id));
1441 $this->assertCronRuns(array(
1442 array(
1443 // On some random day, no email.
1444 'time' => '2014-03-07 01:00:00',
1445 'recipients' => array(),
1446 ),
1447 array(
1448 // A week after their 5th anniversary of graduation, send an email.
1449 'time' => '2018-12-23 20:00:00',
1450 'recipients' => array(array('test-member@example.com')),
1451 ),
1452 ));
1453 $this->callAPISuccess('custom_group', 'delete', array('id' => $createGroup['id']));
1454 }
1455
1456 public function testEventTypeStartDate() {
1457 // Create event+participant with start_date = 20120315, end_date = 20120615.
1458 $participant = $this->createTestObject('CRM_Event_DAO_Participant', array_merge($this->fixtures['participant'], array('status_id' => 2)));
1459 $this->callAPISuccess('Email', 'create', array(
1460 'contact_id' => $participant->contact_id,
1461 'email' => 'test-event@example.com',
1462 ));
1463 $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], array('contact_id' => $participant->contact_id)));
1464
1465 $actionSchedule = $this->fixtures['sched_eventtype_start_1week_before'];
1466 $actionSchedule['entity_value'] = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $participant->event_id, 'event_type_id');
1467 $this->callAPISuccess('action_schedule', 'create', $actionSchedule);
1468
1469 //echo "CREATED\n"; ob_flush(); sleep(20);
1470
1471 // end_date=2012-06-15 ; schedule is 2 weeks before end_date
1472 $this->assertCronRuns(array(
1473 array(
1474 // 2 weeks before
1475 'time' => '2012-03-02 01:00:00',
1476 'recipients' => array(),
1477 ),
1478 array(
1479 // 1 week before
1480 'time' => '2012-03-08 01:00:00',
1481 'recipients' => array(array('test-event@example.com')),
1482 ),
1483 array(
1484 // And then nothing else
1485 'time' => '2012-03-16 01:00:00',
1486 'recipients' => array(),
1487 ),
1488 ));
1489 }
1490
1491 public function testEventTypeEndDateRepeat() {
1492 // Create event+participant with start_date = 20120315, end_date = 20120615.
1493 $participant = $this->createTestObject('CRM_Event_DAO_Participant', array_merge($this->fixtures['participant'], array('status_id' => 2)));
1494 $this->callAPISuccess('Email', 'create', array(
1495 'contact_id' => $participant->contact_id,
1496 'email' => 'test-event@example.com',
1497 ));
1498 $c = $this->callAPISuccess('contact', 'create', array_merge($this->fixtures['contact'], array('contact_id' => $participant->contact_id)));
1499
1500 $actionSchedule = $this->fixtures['sched_eventtype_end_2month_repeat_twice_2_weeks'];
1501 $actionSchedule['entity_value'] = CRM_Core_DAO::getFieldValue('CRM_Event_DAO_Event', $participant->event_id, 'event_type_id');
1502 $this->callAPISuccess('action_schedule', 'create', $actionSchedule);
1503
1504 $this->assertCronRuns(array(
1505 array(
1506 // Almost 2 months.
1507 'time' => '2012-08-13 01:00:00',
1508 'recipients' => array(),
1509 ),
1510 array(
1511 // After the 2-month mark, send an email.
1512 'time' => '2012-08-16 01:00:00',
1513 'recipients' => array(array('test-event@example.com')),
1514 ),
1515 array(
1516 // After 2 months and 1 week, don't repeat yet.
1517 'time' => '2012-08-23 02:00:00',
1518 'recipients' => array(),
1519 ),
1520 array(
1521 // After 2 months and 2 weeks
1522 'time' => '2012-08-30 02:00:00',
1523 'recipients' => array(array('test-event@example.com')),
1524 ),
1525 array(
1526 // After 2 months and 4 week
1527 'time' => '2012-09-13 02:00:00',
1528 'recipients' => array(array('test-event@example.com')),
1529 ),
1530 array(
1531 // After 2 months and 6 weeks
1532 'time' => '2012-09-27 01:00:00',
1533 'recipients' => array(),
1534 ),
1535 ));
1536 }
1537
1538 // TODO // function testMembershipEndDate_NonMatch() { }
1539 // TODO // function testEventTypeStartDate_Match() { }
1540 // TODO // function testEventTypeEndDate_Match() { }
1541 // TODO // function testEventNameStartDate_Match() { }
1542 // TODO // function testEventNameEndDate_Match() { }
1543
1544 /**
1545 * Run a series of cron jobs and make an assertion about email deliveries.
1546 *
1547 * @param array $cronRuns
1548 * array specifying when to run cron and what messages to expect; each item is an array with keys:
1549 * - time: string, e.g. '2012-06-15 21:00:01'
1550 * - recipients: array(array(string)), list of email addresses which should receive messages
1551 */
1552 public function assertCronRuns($cronRuns) {
1553 foreach ($cronRuns as $cronRun) {
1554 CRM_Utils_Time::setTime($cronRun['time']);
1555 $this->callAPISuccess('job', 'send_reminder', array());
1556 $this->mut->assertRecipients($cronRun['recipients']);
1557 if (array_key_exists('subjects', $cronRun)) {
1558 $this->mut->assertSubjects($cronRun['subjects']);
1559 }
1560 $this->mut->clearMessages();
1561 }
1562 }
1563
1564 /**
1565 * @var array(DAO_Name => array(int)) List of items to garbage-collect during tearDown
1566 */
1567 private $_testObjects;
1568
1569 /**
1570 * Sets up the fixture, for example, opens a network connection.
1571 *
1572 * This method is called before a test is executed.
1573 */
1574 protected function _setUp() {
1575 $this->_testObjects = array();
1576 }
1577
1578 /**
1579 * Tears down the fixture, for example, closes a network connection.
1580 *
1581 * This method is called after a test is executed.
1582 */
1583 protected function _tearDown() {
1584 parent::tearDown();
1585 $this->deleteTestObjects();
1586 }
1587
1588 /**
1589 * This is a wrapper for CRM_Core_DAO::createTestObject which tracks
1590 * created entities and provides for brainless cleanup.
1591 *
1592 * @see CRM_Core_DAO::createTestObject
1593 *
1594 * @param $daoName
1595 * @param array $params
1596 * @param int $numObjects
1597 * @param bool $createOnly
1598 *
1599 * @return array|NULL|object
1600 */
1601 public function createTestObject($daoName, $params = array(), $numObjects = 1, $createOnly = FALSE) {
1602 $objects = CRM_Core_DAO::createTestObject($daoName, $params, $numObjects, $createOnly);
1603 if (is_array($objects)) {
1604 $this->registerTestObjects($objects);
1605 }
1606 else {
1607 $this->registerTestObjects(array($objects));
1608 }
1609 return $objects;
1610 }
1611
1612 /**
1613 * @param array $objects
1614 * DAO or BAO objects.
1615 */
1616 public function registerTestObjects($objects) {
1617 //if (is_object($objects)) {
1618 // $objects = array($objects);
1619 //}
1620 foreach ($objects as $object) {
1621 $daoName = preg_replace('/_BAO_/', '_DAO_', get_class($object));
1622 $this->_testObjects[$daoName][] = $object->id;
1623 }
1624 }
1625
1626 public function deleteTestObjects() {
1627 // Note: You might argue that the FK relations between test
1628 // objects could make this problematic; however, it should
1629 // behave intuitively as long as we mentally split our
1630 // test-objects between the "manual/primary records"
1631 // and the "automatic/secondary records"
1632 foreach ($this->_testObjects as $daoName => $daoIds) {
1633 foreach ($daoIds as $daoId) {
1634 CRM_Core_DAO::deleteTestObjects($daoName, array('id' => $daoId));
1635 }
1636 }
1637 $this->_testObjects = array();
1638 }
1639
1640 /**
1641 * Test that the various repetition units work correctly.
1642 * CRM-17028
1643 */
1644 public function testRepetitionFrequencyUnit() {
1645 $membershipTypeParams = array(
1646 'duration_interval' => '1',
1647 'duration_unit' => 'year',
1648 'is_active' => 1,
1649 'period_type' => 'rolling',
1650 );
1651 $membershipType = $this->createTestObject('CRM_Member_DAO_MembershipType', $membershipTypeParams);
1652 $interval_units = array('hour', 'day', 'week', 'month', 'year');
1653 foreach ($interval_units as $interval_unit) {
1654 $membershipEndDate = DateTime::createFromFormat('Y-m-d H:i:s', "2013-03-15 00:00:00");
1655 $contactParams = array(
1656 'contact_type' => 'Individual',
1657 'first_name' => 'Test',
1658 'last_name' => "Interval $interval_unit",
1659 'is_deceased' => 0,
1660 );
1661 $contact = $this->createTestObject('CRM_Contact_DAO_Contact', $contactParams);
1662 $this->assertTrue(is_numeric($contact->id));
1663 $emailParams = array(
1664 'contact_id' => $contact->id,
1665 'email' => "test-member-{$interval_unit}@example.com",
1666 'location_type_id' => 1,
1667 );
1668 $email = $this->createTestObject('CRM_Core_DAO_Email', $emailParams);
1669 $this->assertTrue(is_numeric($email->id));
1670 $membershipParams = array(
1671 'membership_type_id' => $membershipType->id,
1672 'contact_id' => $contact->id,
1673 'join_date' => '20120315',
1674 'start_date' => '20120315',
1675 'end_date' => '20130315',
1676 'is_override' => 0,
1677 'status_id' => 2,
1678 );
1679 $membershipParams['status-id'] = 1;
1680 $membership = $this->createTestObject('CRM_Member_DAO_Membership', $membershipParams);
1681 $actionScheduleParams = $this->fixtures['sched_on_membership_end_date_repeat_interval'];
1682 $actionScheduleParams['entity_value'] = $membershipType->id;
1683 $actionScheduleParams['repetition_frequency_unit'] = $interval_unit;
1684 $actionScheduleParams['repetition_frequency_interval'] = 2;
1685 $actionSchedule = CRM_Core_BAO_ActionSchedule::add($actionScheduleParams);
1686 $this->assertTrue(is_numeric($actionSchedule->id));
1687 $beforeEndDate = $this->createModifiedDateTime($membershipEndDate, '-1 day');
1688 $beforeFirstUnit = $this->createModifiedDateTime($membershipEndDate, "+1 $interval_unit");
1689 $afterFirstUnit = $this->createModifiedDateTime($membershipEndDate, "+2 $interval_unit");
1690 $cronRuns = array(
1691 array(
1692 'time' => $beforeEndDate->format('Y-m-d H:i:s'),
1693 'recipients' => array(),
1694 ),
1695 array(
1696 'time' => $membershipEndDate->format('Y-m-d H:i:s'),
1697 'recipients' => array(array("test-member-{$interval_unit}@example.com")),
1698 ),
1699 array(
1700 'time' => $beforeFirstUnit->format('Y-m-d H:i:s'),
1701 'recipients' => array(),
1702 ),
1703 array(
1704 'time' => $afterFirstUnit->format('Y-m-d H:i:s'),
1705 'recipients' => array(array("test-member-{$interval_unit}@example.com")),
1706 ),
1707 );
1708 $this->assertCronRuns($cronRuns);
1709 $actionSchedule->delete();
1710 $membership->delete();
1711 }
1712 }
1713
1714 public function createModifiedDateTime($origDateTime, $modifyRule) {
1715 $newDateTime = clone($origDateTime);
1716 $newDateTime->modify($modifyRule);
1717 return $newDateTime;
1718 }
1719
1720 }