smart groups as mailing lists were not taking unsubscribed users into account
[civicrm-core.git] / tests / phpunit / CRM / Mailing / BAO / MailingTest.php
CommitLineData
9f0a25d7
J
1<?php
2/*
3 +--------------------------------------------------------------------+
2fe49090 4 | CiviCRM version 5 |
9f0a25d7 5 +--------------------------------------------------------------------+
8c9251b3 6 | Copyright CiviCRM LLC (c) 2004-2018 |
9f0a25d7
J
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_Mailing_BAO_MailingTest
30 */
31class CRM_Mailing_BAO_MailingTest extends CiviUnitTestCase {
32
fae688ec 33 protected $allowedContactId = 0;
34
9f0a25d7
J
35 public function setUp() {
36 parent::setUp();
37 }
38
df3320dc 39 public function tearDown() {
40 global $dbLocale;
41 if ($dbLocale) {
42 CRM_Core_I18n_Schema::makeSinglelingual('en_US');
43 }
44 parent::tearDown();
45 }
46
6ff6f4f2
J
47 /**
48 * Helper function to assert whether the calculated recipients of a mailing
49 * match the expected list
50 *
51 * @param $mailingID
52 * @param $expectedRecipients array
53 * Array of contact ID that should be in the recipient list.
54 */
55 private function assertRecipientsCorrect($mailingID, $expectedRecipients) {
56
57 // Reset keys to ensure match
58 $expectedRecipients = array_values($expectedRecipients);
59
60 // Load the recipients as a list of contact IDs
61 CRM_Mailing_BAO_Mailing::getRecipients($mailingID);
62 $recipients = $this->callAPISuccess('MailingRecipients', 'get', array('mailing_id' => $mailingID));
63 $contactIDs = array();
64 foreach ($recipients['values'] as $recipient) {
65 $contactIDs[] = $recipient['contact_id'];
66 }
67
68 // Check the lists match
69 $this->assertTreeEquals($expectedRecipients, $contactIDs);
70 }
71
72 /**
73 * Helper function to create a mailing include/exclude group.
74 *
75 * @param $mailingID
76 * @param $groupID
77 * @param string $type
78 * @return array|int
79 */
80 private function createMailingGroup($mailingID, $groupID, $type = 'Include') {
81 return $this->callAPISuccess('MailingGroup', 'create', array(
82 'mailing_id' => $mailingID,
83 'group_type' => $type,
df3320dc 84 'entity_table' => CRM_Contact_BAO_Group::getTableName(),
6ff6f4f2
J
85 'entity_id' => $groupID,
86 ));
87 }
88
fae688ec 89 /**
90 * Test to ensure that using ACL permitted contacts are correctly fetched for bulk mailing
91 */
92 public function testgetRecipientsUsingACL() {
93 $this->prepareForACLs();
94 $this->createLoggedInUser();
95 // create hook to build ACL where clause which choses $this->allowedContactId as the only contact to be considered as mail recipient
96 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereAllowedOnlyOne'));
97 CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviCRM', 'view my contact');
98
99 // Create dummy group and assign 2 contacts
100 $name = 'Test static group ' . substr(sha1(rand()), 0, 7);
101 $groupID = $this->groupCreate([
102 'name' => $name,
103 'title' => $name,
104 'is_active' => 1,
105 ]);
106 // Create 2 contacts where one of them identified as $this->allowedContactId will be used in ACL where clause
107 $contactID1 = $this->individualCreate(array(), 0);
108 $this->allowedContactId = $this->individualCreate(array(), 1);
109 $this->callAPISuccess('GroupContact', 'Create', array(
110 'group_id' => $groupID,
111 'contact_id' => $contactID1,
112 ));
113 $this->callAPISuccess('GroupContact', 'Create', array(
114 'group_id' => $groupID,
115 'contact_id' => $this->allowedContactId,
116 ));
117
118 // Create dummy mailing
119 $mailingID = $this->callAPISuccess('Mailing', 'create', array())['id'];
120 $this->createMailingGroup($mailingID, $groupID);
121
122 // Check that the desired contact (identified as Contact ID - $this->allowedContactId) is the only
123 // contact chosen as mail recipient
124 $expectedContactIDs = [$this->allowedContactId];
125 $this->assertRecipientsCorrect($mailingID, $expectedContactIDs);
126
127 $this->cleanUpAfterACLs();
2acf8c58 128 $this->callAPISuccess('Group', 'Delete', ['id' => $groupID]);
fae688ec 129 $this->contactDelete($contactID1);
130 $this->contactDelete($this->allowedContactId);
131 }
132
e3d924ca
SL
133 /**
134 * Test mailing receipients when using previous mailing as include and contact is in exclude as well
135 */
136 public function testMailingIncludePreviousMailingExcludeGroup() {
137 $groupName = 'Test static group ' . substr(sha1(rand()), 0, 7);
138 $groupName2 = 'Test static group 2' . substr(sha1(rand()), 0, 7);
139 $groupID = $this->groupCreate([
140 'name' => $groupName,
141 'title' => $groupName,
142 'is_active' => 1,
143 ]);
144 $groupID2 = $this->groupCreate([
145 'name' => $groupName2,
146 'title' => $groupName2,
147 'is_active' => 1,
148 ]);
149 $contactID = $this->individualCreate(array(), 0);
150 $contactID2 = $this->individualCreate(array(), 2);
151 $this->callAPISuccess('GroupContact', 'Create', array(
152 'group_id' => $groupID,
153 'contact_id' => $contactID,
154 ));
155 $this->callAPISuccess('GroupContact', 'Create', array(
156 'group_id' => $groupID,
157 'contact_id' => $contactID2,
158 ));
159 $this->callAPISuccess('GroupContact', 'Create', array(
160 'group_id' => $groupID2,
161 'contact_id' => $contactID2,
162 ));
163 // Create dummy mailing
164 $mailingID = $this->callAPISuccess('Mailing', 'create', array())['id'];
165 $this->createMailingGroup($mailingID, $groupID);
166 $expectedContactIDs = [$contactID, $contactID2];
167 $this->assertRecipientsCorrect($mailingID, $expectedContactIDs);
168 $mailingID2 = $this->callAPISuccess('Mailing', 'create', array())['id'];
169 $this->createMailingGroup($mailingID2, $groupID2, 'Exclude');
170 $this->callAPISuccess('MailingGroup', 'create', array(
171 'mailing_id' => $mailingID2,
172 'group_type' => 'Include',
173 'entity_table' => CRM_Mailing_BAO_Mailing::getTableName(),
174 'entity_id' => $mailingID,
175 ));
176 $expectedContactIDs = [$contactID];
177 $this->assertRecipientsCorrect($mailingID2, $expectedContactIDs);
178 $this->callAPISuccess('mailing', 'delete', ['id' => $mailingID2]);
179 $this->callAPISuccess('mailing', 'delete', ['id' => $mailingID]);
180 $this->callAPISuccess('group', 'delete', ['id' => $groupID]);
181 $this->callAPISuccess('group', 'delete', ['id' => $groupID2]);
182 $this->callAPISuccess('contact', 'delete', ['id' => $contactID, 'skip_undelete' => TRUE]);
183 $this->callAPISuccess('contact', 'delete', ['id' => $contactID2, 'skip_undelete' => TRUE]);
184 }
185
2acf8c58
SL
186 /**
187 * Test verify that a disabled mailing group doesn't prvent access to the mailing generated with the group.
188 */
189 public function testGetMailingDisabledGroup() {
190 $this->prepareForACLs();
191 $this->createLoggedInUser();
192 // create hook to build ACL where clause which choses $this->allowedContactId as the only contact to be considered as mail recipient
193 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereAllowedOnlyOne'));
194 $this->hookClass->setHook('civicrm_aclGroup', array($this, 'hook_civicrm_aclGroup'));
195 CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviCRM', 'edit groups');
196 // Create dummy group and assign 2 contacts
197 $name = 'Test static group ' . substr(sha1(rand()), 0, 7);
198 $groupID = $this->groupCreate([
199 'name' => $name,
200 'title' => $name,
201 'is_active' => 1,
202 ]);
203 $contactID = $this->individualCreate(array(), 0);
204 $this->callAPISuccess('GroupContact', 'Create', array(
205 'group_id' => $groupID,
206 'contact_id' => $contactID,
207 ));
208
209 // Create dummy mailing
210 $mailingID = $this->callAPISuccess('Mailing', 'create', array())['id'];
211 $this->createMailingGroup($mailingID, $groupID);
212 // Now disable the group.
213 $this->callAPISuccess('group', 'create', [
214 'id' => $groupID,
215 'is_active' => 0,
216 ]);
217 $groups = CRM_Mailing_BAO_Mailing::mailingACLIDs();
218 $this->assertTrue(in_array($groupID, $groups));
219 $this->cleanUpAfterACLs();
220 $this->contactDelete($contactID);
221 }
222
fae688ec 223 /**
224 * Build ACL where clause
225 *
226 * @implements CRM_Utils_Hook::aclWhereClause
227 *
228 * @param string $type
229 * @param array $tables
230 * @param array $whereTables
231 * @param int $contactID
232 * @param string $where
233 */
234 public function aclWhereAllowedOnlyOne($type, &$tables, &$whereTables, &$contactID, &$where) {
235 $where = " contact_a.id = " . $this->allowedContactId;
236 }
237
2acf8c58
SL
238 /**
239 * Implements ACLGroup hook.
240 *
241 * @implements CRM_Utils_Hook::aclGroup
242 *
243 * aclGroup function returns a list of permitted groups
244 * @param string $type
245 * @param int $contactID
246 * @param string $tableName
247 * @param array $allGroups
248 * @param array $currentGroups
249 */
250 public function hook_civicrm_aclGroup($type, $contactID, $tableName, &$allGroups, &$currentGroups) {
251 //don't use api - you will get a loop
252 $sql = " SELECT * FROM civicrm_group";
253 $groups = array();
254 $dao = CRM_Core_DAO::executeQuery($sql);
255 while ($dao->fetch()) {
256 $groups[] = $dao->id;
257 }
258 if (!empty($allGroups)) {
259 //all groups is empty if we really mean all groups but if a filter like 'is_disabled' is already applied
260 // it is populated, ajax calls from Manage Groups will leave empty but calls from New Mailing pass in a filtered list
261 $currentGroups = array_intersect($groups, array_flip($allGroups));
262 }
263 else {
264 $currentGroups = $groups;
265 }
266 }
267
268
251a8849 269 /**
7ff80daf
J
270 * @todo Missing tests:
271 * - Ensure opt out emails are not mailed
272 * - Ensure 'stop' emails are not mailed
273 * - Ensure the deceased are not mailed
274 * - Tests for getLocationFilterAndOrderBy (selecting correct 'type')
275 * - ...
251a8849
J
276 */
277
7ff80daf
J
278 /**
279 * Test to ensure that static and smart mailing groups can be added to an
280 * email mailing as 'include' or 'exclude' groups - and the members are
281 * included or excluded appropriately.
282 *
283 * contact 0 : static 0 (inc) + smart 5 (exc)
284 * contact 1 : static 0 (inc)
285 * contact 2 : static 1 (inc)
286 * contact 3 : static 1 (inc)
287 * contact 4 : static 2 (exc) + smart 3 (inc)
288 * contact 5 : smart 3 (inc)
289 * contact 6 : smart 4 (inc)
290 * contact 7 : smart 4 (inc)
70170c4f 291 * contact 8 : smart 5 (base)
292 *
293 * here 'contact 1 : static 0 (inc)' identified as static group $groupIDs[0]
294 * that has 'contact 1' identified as $contactIDs[0] and Included in the mailing recipient list
7ff80daf
J
295 */
296 public function testgetRecipientsEmailGroupIncludeExclude() {
70170c4f 297 // Set up groups; 3 standard, 4 smart
7ff80daf 298 $groupIDs = array();
70170c4f 299 for ($i = 0; $i < 7; $i++) {
7ff80daf
J
300 $params = array(
301 'name' => 'Test static group ' . $i,
302 'title' => 'Test static group ' . $i,
303 'is_active' => 1,
304 );
305 if ($i < 3) {
306 $groupIDs[$i] = $this->groupCreate($params);
307 }
308 else {
309 $groupIDs[$i] = $this->smartGroupCreate(array(
70170c4f 310 'formValues' => ['last_name' => (($i == 6) ? 'smart5' : 'smart' . $i)],
7ff80daf
J
311 ), $params);
312 }
313 }
314
315 // Create contacts
316 $contactIDs = array(
70170c4f 317 $this->individualCreate(array('last_name' => 'smart5'), 0),
318 $this->individualCreate(array(), 1),
319 $this->individualCreate(array(), 2),
320 $this->individualCreate(array(), 3),
321 $this->individualCreate(array('last_name' => 'smart3'), 4),
322 $this->individualCreate(array('last_name' => 'smart3'), 5),
323 $this->individualCreate(array('last_name' => 'smart4'), 6),
324 $this->individualCreate(array('last_name' => 'smart4'), 7),
325 $this->individualCreate(array('last_name' => 'smart5'), 8),
7ff80daf
J
326 );
327
328 // Add contacts to static groups
329 $this->callAPISuccess('GroupContact', 'Create', array(
330 'group_id' => $groupIDs[0],
331 'contact_id' => $contactIDs[0],
332 ));
333 $this->callAPISuccess('GroupContact', 'Create', array(
334 'group_id' => $groupIDs[0],
335 'contact_id' => $contactIDs[1],
336 ));
337 $this->callAPISuccess('GroupContact', 'Create', array(
338 'group_id' => $groupIDs[1],
339 'contact_id' => $contactIDs[2],
340 ));
341 $this->callAPISuccess('GroupContact', 'Create', array(
342 'group_id' => $groupIDs[1],
343 'contact_id' => $contactIDs[3],
344 ));
345 $this->callAPISuccess('GroupContact', 'Create', array(
346 'group_id' => $groupIDs[2],
347 'contact_id' => $contactIDs[4],
348 ));
349
350 // Force rebuild the smart groups
70170c4f 351 for ($i = 3; $i < 7; $i++) {
7ff80daf
J
352 $group = new CRM_Contact_DAO_Group();
353 $group->id = $groupIDs[$i];
354 $group->find(TRUE);
355 CRM_Contact_BAO_GroupContactCache::load($group, TRUE);
356 }
357
358 // Check that we can include static groups in the mailing.
359 // Expected: Contacts [0-3] should be included.
360 $mailing = $this->callAPISuccess('Mailing', 'create', array());
361 $this->createMailingGroup($mailing['id'], $groupIDs[0]);
362 $this->createMailingGroup($mailing['id'], $groupIDs[1]);
70170c4f 363 $this->createMailingGroup($mailing['id'], $groupIDs[6], 'Base');
7ff80daf 364 $expected = $contactIDs;
70170c4f 365 unset($expected[4], $expected[5], $expected[6], $expected[7], $expected[8]);
7ff80daf
J
366 $this->assertRecipientsCorrect($mailing['id'], $expected);
367
368 // Check that we can include smart groups in the mailing too.
369 // Expected: All contacts should be included.
df3320dc 370 // Also (dev/mail/6): Enable multilingual mode to check that restructing group doesn't affect recipient rebuilding
371 $this->enableMultilingual();
7ff80daf
J
372 $this->createMailingGroup($mailing['id'], $groupIDs[3]);
373 $this->createMailingGroup($mailing['id'], $groupIDs[4]);
70170c4f 374 $this->createMailingGroup($mailing['id'], $groupIDs[5]);
375 // Check that all the contacts whould be present is recipient list as static group [0], [1] and [2] and
376 // smart groups [3], [4] and [5] is included in the recipient listing.
377 // NOTE: that contact[8] is present in both included smart group[5] and base smart group [6] so it will be
378 // present in recipient list as contact(s) from Base smart groups are not excluded the list as per (dev/mail/13)
7ff80daf
J
379 $this->assertRecipientsCorrect($mailing['id'], $contactIDs);
380
381 // Check we can exclude static groups from the mailing.
382 // Expected: All contacts except [4]
383 $this->createMailingGroup($mailing['id'], $groupIDs[2], 'Exclude');
384 $expected = $contactIDs;
385 unset($expected[4]);
70170c4f 386 // NOTE: as per (dev/mail/13) if a contact A is present in smartGroup [5] which is Included in the mailing AND
387 // also present in another smartGroup [6] which is considered as Base group, then contact A should not be excluded from
388 // the recipient list due to later
7ff80daf
J
389 $this->assertRecipientsCorrect($mailing['id'], $expected);
390
391 // Check we can exclude smart groups from the mailing too.
70170c4f 392 // Expected: All contacts except [0], [4] and [8]
7ff80daf
J
393 $this->createMailingGroup($mailing['id'], $groupIDs[5], 'Exclude');
394 $expected = $contactIDs;
70170c4f 395 // As contact [0] and [8] belongs to excluded smart group[5] and base smart group[6] respectively,
396 // both these contacts should not be present in the mailing list
397 unset($expected[0], $expected[4], $expected[8]);
7ff80daf
J
398 $this->assertRecipientsCorrect($mailing['id'], $expected);
399
c6ad7d51
T
400 // Tear down: delete mailing, groups, contacts
401 $this->deleteMailing($mailing['id']);
402
403 // Create a New mailing, Testing contacts removed from smart group.
404 // In this case groupIDs6 will only pick up contacts[0] amd contacts[8] with it's
405 // criteria. However we are deliberly going to remove contactIds[8] from the group
406 // Which should mean the mainling only finds 1 contact that is contactIds[0]
407 $mailing = $this->callAPISuccess('Mailing', 'create', array());
408 $this->callAPISuccess('GroupContact', 'Create', array(
409 'group_id' => $groupIDs[6],
410 'contact_id' => $contactIDs[8],
411 'status' => 'Removed',
412 ));
413 $this->createMailingGroup($mailing['id'], $groupIDs[6]);
414 $this->assertRecipientsCorrect($mailing['id'], [$contactIDs[0]]);
7ff80daf
J
415 // Tear down: delete mailing, groups, contacts
416 $this->deleteMailing($mailing['id']);
417 foreach ($groupIDs as $groupID) {
418 $this->groupDelete($groupID);
419 }
420 foreach ($contactIDs as $contactID) {
421 $this->contactDelete($contactID);
422 }
7ff80daf
J
423 }
424
9f0a25d7 425 /**
6f3a35e0 426 * Test CRM_Mailing_BAO_Mailing::getRecipients() on sms mode
9f0a25d7 427 */
7ff80daf 428 public function testgetRecipientsSMS() {
9f0a25d7
J
429 // Tests for SMS bulk mailing recipients
430 // +CRM-21320 Ensure primary mobile number is selected over non-primary
431
432 // Setup
6f3a35e0 433 $smartGroupParams = array(
434 'formValues' => array('contact_type' => array('IN' => array('Individual'))),
435 );
436 $group = $this->smartGroupCreate($smartGroupParams);
9f0a25d7
J
437 $sms_provider = $this->callAPISuccess('SmsProvider', 'create', array(
438 'sequential' => 1,
439 'name' => 1,
440 'title' => "Test",
441 'username' => "Test",
442 'password' => "Test",
443 'api_type' => 1,
444 'is_active' => 1,
445 ));
446
6f3a35e0 447 // Create Contact 1 and add in group
448 $contactID1 = $this->individualCreate(array(), 0);
9f0a25d7
J
449 $this->callAPISuccess('GroupContact', 'Create', array(
450 'group_id' => $group,
6f3a35e0 451 'contact_id' => $contactID1,
9f0a25d7
J
452 ));
453
6f3a35e0 454 // Create contact 2 and add in group
455 $contactID2 = $this->individualCreate(array(), 1);
9f0a25d7
J
456 $this->callAPISuccess('GroupContact', 'Create', array(
457 'group_id' => $group,
6f3a35e0 458 'contact_id' => $contactID2,
9f0a25d7
J
459 ));
460
6f3a35e0 461 $contactIDPhoneRecords = array(
462 $contactID1 => array(
463 'primary_phone_id' => CRM_Utils_Array::value('id', $this->callAPISuccess('Phone', 'create', array(
464 'contact_id' => $contactID1,
465 'phone' => "01 01",
466 'location_type_id' => "Home",
467 'phone_type_id' => "Mobile",
468 'is_primary' => 1,
469 ))),
470 'other_phone_id' => CRM_Utils_Array::value('id', $this->callAPISuccess('Phone', 'create', array(
471 'contact_id' => $contactID1,
472 'phone' => "01 02",
473 'location_type_id' => "Work",
474 'phone_type_id' => "Mobile",
475 'is_primary' => 0,
476 ))),
477 ),
251a8849 478 // Create the non-primary with a lower ID than the primary, to test CRM-21320
6f3a35e0 479 $contactID2 => array(
251a8849 480 'other_phone_id' => CRM_Utils_Array::value('id', $this->callAPISuccess('Phone', 'create', array(
6f3a35e0 481 'contact_id' => $contactID2,
482 'phone' => "02 01",
483 'location_type_id' => "Home",
484 'phone_type_id' => "Mobile",
251a8849 485 'is_primary' => 0,
6f3a35e0 486 ))),
251a8849 487 'primary_phone_id' => CRM_Utils_Array::value('id', $this->callAPISuccess('Phone', 'create', array(
6f3a35e0 488 'contact_id' => $contactID2,
489 'phone' => "02 02",
490 'location_type_id' => "Work",
491 'phone_type_id' => "Mobile",
251a8849 492 'is_primary' => 1,
6f3a35e0 493 ))),
494 ),
495 );
496
9f0a25d7 497 // Prepare expected results
6f3a35e0 498 $checkPhoneIDs = array(
499 $contactID1 => $contactIDPhoneRecords[$contactID1]['primary_phone_id'],
500 $contactID2 => $contactIDPhoneRecords[$contactID2]['primary_phone_id'],
9f0a25d7
J
501 );
502
503 // Create mailing
504 $mailing = $this->callAPISuccess('Mailing', 'create', array('sms_provider_id' => $sms_provider['id']));
6ff6f4f2 505 $mailingInclude = $this->createMailingGroup($mailing['id'], $group);
9f0a25d7
J
506
507 // Get recipients
6ff6f4f2 508 CRM_Mailing_BAO_Mailing::getRecipients($mailing['id']);
9f0a25d7
J
509 $recipients = $this->callAPISuccess('MailingRecipients', 'get', array('mailing_id' => $mailing['id']));
510
511 // Check the count is correct
512 $this->assertEquals(2, $recipients['count'], 'Check recipient count');
513
514 // Check we got the 'primary' mobile for both contacts
515 foreach ($recipients['values'] as $value) {
6f3a35e0 516 $this->assertEquals($value['phone_id'], $checkPhoneIDs[$value['contact_id']], 'Check correct phone number for contact ' . $value['contact_id']);
9f0a25d7
J
517 }
518
519 // Tidy up
520 $this->deleteMailing($mailing['id']);
521 $this->callAPISuccess('SmsProvider', 'Delete', array('id' => $sms_provider['id']));
522 $this->groupDelete($group);
6f3a35e0 523 $this->contactDelete($contactID1);
524 $this->contactDelete($contactID2);
9f0a25d7
J
525 }
526
737f12a7 527 /**
528 * Test alterMailingRecipients Hook which is called twice when we create a Mailing,
529 * 1. In the first call we will modify the mailing filter to include only deceased recipients
530 * 2. In the second call we will check if only deceased recipient is populated in MailingRecipient table
531 */
532 public function testAlterMailingRecipientsHook() {
533 $groupID = $this->groupCreate();
be2c9578 534 $this->tagCreate(array('name' => 'Tagged'));
737f12a7 535
536 // Create deseased Contact 1 and add in group
537 $contactID1 = $this->individualCreate(array('email' => 'abc@test.com', 'is_deceased' => 1), 0);
538 // Create deseased Contact 2 and add in group
539 $contactID2 = $this->individualCreate(array('email' => 'def@test.com'), 1);
be2c9578 540 // Create deseased Contact 3 and add in group
541 $contactID3 = $this->individualCreate(array('email' => 'ghi@test.com', 'is_deceased' => 1), 2);
542
737f12a7 543 // Add both the created contacts in group
544 $this->callAPISuccess('GroupContact', 'Create', array(
545 'group_id' => $groupID,
546 'contact_id' => $contactID1,
547 ));
548 $this->callAPISuccess('GroupContact', 'Create', array(
549 'group_id' => $groupID,
550 'contact_id' => $contactID2,
551 ));
be2c9578 552 $this->callAPISuccess('GroupContact', 'Create', array(
553 'group_id' => $groupID,
554 'contact_id' => $contactID3,
555 ));
556 $this->entityTagAdd(array('contact_id' => $contactID3, 'tag_id' => 'Tagged'));
557
737f12a7 558 // trigger the alterMailingRecipients hook
559 $this->hookClass->setHook('civicrm_alterMailingRecipients', array($this, 'alterMailingRecipients'));
560
561 // create mailing that will trigger alterMailingRecipients hook
562 $params = array(
563 'name' => 'mailing name',
564 'subject' => 'Test Subject',
565 'body_html' => '<p>HTML Body</p>',
566 'text_html' => 'Text Body',
567 'created_id' => 1,
568 'groups' => array('include' => array($groupID)),
569 'scheduled_date' => 'now',
570 );
571 $this->callAPISuccess('Mailing', 'create', $params);
572 }
573
574 /**
575 * @implements CRM_Utils_Hook::alterMailingRecipients
576 *
577 * @param object $mailingObject
be2c9578 578 * @param array $criteria
737f12a7 579 * @param string $context
580 */
be2c9578 581 public function alterMailingRecipients(&$mailingObject, &$criteria, $context) {
737f12a7 582 if ($context == 'pre') {
be2c9578 583 // modify the filter to include only deceased recipient(s) that is Tagged
584 $criteria['is_deceased'] = CRM_Utils_SQL_Select::fragment()->where("civicrm_contact.is_deceased = 1");
585 $criteria['tagged_contact'] = CRM_Utils_SQL_Select::fragment()
586 ->join('civicrm_entity_tag', "INNER JOIN civicrm_entity_tag et ON et.entity_id = civicrm_contact.id AND et.entity_table = 'civicrm_contact'")
587 ->join('civicrm_tag', "INNER JOIN civicrm_tag t ON t.id = et.tag_id")
588 ->where("t.name = 'Tagged'");
737f12a7 589 }
590 else {
591 $mailingRecipients = $this->callAPISuccess('MailingRecipients', 'get', array(
592 'mailing_id' => $mailingObject->id,
593 'api.Email.getvalue' => array(
594 'id' => '$value.email_id',
595 'return' => 'email',
596 ),
597 ));
598 $this->assertEquals(1, $mailingRecipients['count'], 'Check recipient count');
be2c9578 599 $this->assertEquals('ghi@test.com', $mailingRecipients['values'][$mailingRecipients['id']]['api.Email.getvalue'], 'Check if recipient email belong to deceased contact');
737f12a7 600 }
601 }
602
9f0a25d7 603}