47488d9a583a68f5123260285b416925028ffec7
[civicrm-core.git] / tests / phpunit / CRM / Contact / BAO / GroupContactTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2020 |
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 * Test class for CRM_Contact_BAO_GroupContact BAO
30 *
31 * @package CiviCRM
32 * @group headless
33 */
34 class CRM_Contact_BAO_GroupContactTest extends CiviUnitTestCase {
35
36 /**
37 * Sets up the fixture, for example, opens a network connection.
38 * This method is called before a test is executed.
39 */
40 protected function setUp() {
41 parent::setUp();
42 }
43
44 /**
45 * Tears down the fixture, for example, closes a network connection.
46 *
47 * This method is called after a test is executed.
48 */
49 protected function tearDown() {
50 }
51
52 /**
53 * Test case for add( ).
54 */
55 public function testAdd() {
56
57 //creates a test group contact by recursively creation
58 //lets create 10 groupContacts for fun
59 $groupContacts = CRM_Core_DAO::createTestObject('CRM_Contact_DAO_GroupContact', NULL, 10);
60
61 //check the group contact id is not null for each of them
62 foreach ($groupContacts as $gc) {
63 $this->assertNotNull($gc->id);
64 }
65
66 //cleanup
67 foreach ($groupContacts as $gc) {
68 $gc->deleteTestObjects('CRM_Contact_DAO_GroupContact');
69 }
70 }
71
72 /**
73 * Test case for getGroupId( )
74 */
75 public function testGetGroupId() {
76
77 //creates a test groupContact object
78 //force group_id to 1 so we can compare
79 $groupContact = CRM_Core_DAO::createTestObject('CRM_Contact_DAO_GroupContact');
80
81 //check the group contact id is not null
82 $this->assertNotNull($groupContact->id);
83
84 $groupId = CRM_Core_DAO::singleValueQuery('select max(id) from civicrm_group');
85
86 $this->assertEquals($groupContact->group_id, $groupId, 'Check for group_id');
87
88 //cleanup
89 $groupContact->deleteTestObjects('CRM_Contact_DAO_GroupContact');
90 }
91
92 /**
93 * Test case for contact search: CRM-6706, CRM-6586 Parent Group search should return contacts from child groups too.
94 *
95 * @throws \Exception
96 */
97 public function testContactSearchByParentGroup() {
98 // create a parent group
99 $parentGroup = $this->callAPISuccess('Group', 'create', [
100 'title' => 'Parent Group',
101 'description' => 'Parent Group',
102 'visibility' => 'User and User Admin Only',
103 'is_active' => 1,
104 ]);
105
106 // create a child group
107 $childGroup = $this->callAPISuccess('Group', 'create', [
108 'title' => 'Child Group',
109 'description' => 'Child Group',
110 'visibility' => 'User and User Admin Only',
111 'parents' => $parentGroup['id'],
112 'is_active' => 1,
113 ]);
114
115 // create smart group based on saved criteria Gender = Male
116 $batch = $this->callAPISuccess('SavedSearch', 'create', [
117 'form_values' => 'a:1:{i:0;a:5:{i:0;s:9:"gender_id";i:1;s:1:"=";i:2;i:2;i:3;i:0;i:4;i:0;}}',
118 ]);
119 // Create contact with Gender - Male
120 $childSmartGroupContact = $this->individualCreate([
121 'gender_id' => "Male",
122 'first_name' => 'C',
123 ], 1);
124 // then create smart group
125 $childSmartGroup = $this->callAPISuccess('Group', 'create', [
126 'title' => 'Child Smart Group',
127 'description' => 'Child Smart Group',
128 'visibility' => 'User and User Admin Only',
129 'saved_search_id' => $batch['id'],
130 'is_active' => 1,
131 'parents' => $parentGroup['id'],
132 ]);
133
134 $this->callAPISuccess('Group', 'create', [
135 'id' => $parentGroup['id'],
136 'children' => implode(',', [$childGroup['id'], $childSmartGroup['id']]),
137 ]);
138
139 // Create a contact within parent group
140 $parentContactParams = [
141 'first_name' => 'Parent1 Fname',
142 'last_name' => 'Parent1 Lname',
143 'group' => [$parentGroup['id'] => 1],
144 ];
145 $parentContact = $this->individualCreate($parentContactParams);
146
147 // create a contact within child dgroup
148 $childContactParams = [
149 'first_name' => 'Child1 Fname',
150 'last_name' => 'Child2 Lname',
151 'group' => [$childGroup['id'] => 1],
152 ];
153 $childContact = $this->individualCreate($childContactParams);
154
155 // Check if searching by parent group returns both parent and child group contacts
156 $result = $this->callAPISuccess('contact', 'get', [
157 'group' => $parentGroup['id'],
158 ]);
159 $validContactIds = [$parentContact, $childContact];
160 $resultContactIds = [];
161 foreach ($result['values'] as $k => $v) {
162 $resultContactIds[] = $v['contact_id'];
163 }
164 $this->assertEquals(3, count($resultContactIds), 'Check the count of returned values');
165 $this->assertEquals([], array_diff($validContactIds, $resultContactIds), 'Check that the difference between two arrays should be blank array');
166
167 // Check if searching by child group returns just child group contacts
168 $result = $this->callAPISuccess('contact', 'get', [
169 'group' => $childGroup['id'],
170 ]);
171 $validChildContactIds = [$childContact];
172 $resultChildContactIds = [];
173 foreach ($result['values'] as $k => $v) {
174 $resultChildContactIds[] = $v['contact_id'];
175 }
176 $this->assertEquals(1, count($resultChildContactIds), 'Check the count of returned values');
177 $this->assertEquals([], array_diff($validChildContactIds, $resultChildContactIds), 'Check that the difference between two arrays should be blank array');
178
179 // Check if searching by smart child group returns just smart child group contacts
180 $result = $this->callAPISuccess('contact', 'get', [
181 'group' => $childSmartGroup['id'],
182 ]);
183 $validChildContactIds = [$childSmartGroupContact];
184 $resultChildContactIds = [];
185 foreach ($result['values'] as $k => $v) {
186 $resultChildContactIds[] = $v['contact_id'];
187 }
188 $this->assertEquals(1, count($resultChildContactIds), 'Check the count of returned values');
189 $this->assertEquals([], array_diff($validChildContactIds, $resultChildContactIds), 'Check that the difference between two arrays should be blank array');
190
191 //cleanup
192 $this->callAPISuccess('Contact', 'delete', ['id' => $parentContact]);
193 $this->callAPISuccess('Contact', 'delete', ['id' => $childContact]);
194 $this->callAPISuccess('Contact', 'delete', ['id' => $childSmartGroupContact]);
195 }
196
197 /**
198 * CRM-19698: Test case for combine contact search in regular and smart group
199 */
200 public function testContactCombineGroupSearch() {
201 // create regular group based
202 $regularGroup = $this->callAPISuccess('Group', 'create', [
203 'title' => 'Regular Group',
204 'description' => 'Regular Group',
205 'visibility' => 'User and User Admin Only',
206 'is_active' => 1,
207 ]);
208
209 // Create contact with Gender - Male
210 $contact1 = $this->individualCreate([
211 'gender_id' => "Male",
212 'first_name' => 'A',
213 ]);
214
215 // Create contact with Gender - Male and in regular group
216 $contact2 = $this->individualCreate([
217 'group' => [$regularGroup['id'] => 1],
218 'gender_id' => "Male",
219 'first_name' => 'B',
220 ], 1);
221
222 // Create contact with Gender - Female and in regular group
223 $contact3 = $this->individualCreate([
224 'group' => [$regularGroup['id'] => 1],
225 'gender_id' => "Female",
226 'first_name' => 'C',
227 ], 1);
228
229 // create smart group based on saved criteria Gender = Male
230 $batch = $this->callAPISuccess('SavedSearch', 'create', [
231 'form_values' => 'a:1:{i:0;a:5:{i:0;s:9:"gender_id";i:1;s:1:"=";i:2;i:2;i:3;i:0;i:4;i:0;}}',
232 ]);
233 $smartGroup = $this->callAPISuccess('Group', 'create', [
234 'title' => 'Smart Group',
235 'description' => 'Smart Group',
236 'visibility' => 'User and User Admin Only',
237 'saved_search_id' => $batch['id'],
238 'is_active' => 1,
239 ]);
240
241 $useCases = [
242 //Case 1: Find all contacts in regular group
243 [
244 'form_value' => ['group' => $regularGroup['id']],
245 'expected_count' => 2,
246 'expected_contact' => [$contact2, $contact3],
247 ],
248 //Case 2: Find all contacts in smart group
249 [
250 'form_value' => ['group' => $smartGroup['id']],
251 'expected_count' => 2,
252 'expected_contact' => [$contact1, $contact2],
253 ],
254 //Case 3: Find all contacts in regular group and smart group
255 [
256 'form_value' => ['group' => ['IN' => [$regularGroup['id'], $smartGroup['id']]]],
257 'expected_count' => 3,
258 'expected_contact' => [$contact1, $contact2, $contact3],
259 ],
260 ];
261 foreach ($useCases as $case) {
262 $query = new CRM_Contact_BAO_Query(CRM_Contact_BAO_Query::convertFormValues($case['form_value']));
263 list($select, $from, $where, $having) = $query->query();
264 $groupContacts = CRM_Core_DAO::executeQuery("SELECT DISTINCT contact_a.* $from $where ORDER BY contact_a.first_name")->fetchAll();
265 foreach ($groupContacts as $key => $value) {
266 $groupContacts[$key] = $value['id'];
267 }
268 $this->assertEquals($case['expected_count'], count($groupContacts));
269 $this->checkArrayEquals($case['expected_contact'], $groupContacts);
270 }
271 }
272
273 /**
274 * CRM-19333: Test case for contact search on basis of group type
275 */
276 public function testbyGroupType() {
277 $groupTypes = CRM_Core_BAO_OptionValue::getOptionValuesAssocArrayFromName('group_type');
278 $mailingListGT = array_search('Mailing List', $groupTypes);
279 $accessControlGT = array_search('Access Control', $groupTypes);
280
281 // create group with group type - Mailing list
282 $group1 = $this->callAPISuccess('Group', 'create', [
283 'title' => 'Group 1',
284 'visibility' => 'User and User Admin Only',
285 'is_active' => 1,
286 'group_type' => $mailingListGT,
287 ]);
288
289 // create group with group type - Access Control
290 $group2 = $this->callAPISuccess('Group', 'create', [
291 'title' => 'Group 2',
292 'visibility' => 'User and User Admin Only',
293 'is_active' => 1,
294 'group_type' => $accessControlGT,
295 ]);
296
297 // create contact in 'Group 1'
298 $contact1 = $this->individualCreate([
299 'group' => [$group1['id'] => 1],
300 'first_name' => 'A',
301 ]);
302
303 // create contact in 'Group 2'
304 $contact2 = $this->individualCreate([
305 'group' => [$group2['id'] => 1],
306 'first_name' => 'B',
307 ], 1);
308
309 $useCases = [
310 //Case 1: Find contacts in group type - Mailing List
311 [
312 'form_value' => ['group_type' => [$mailingListGT]],
313 'expected_count' => 1,
314 'expected_contact' => [$contact1],
315 ],
316 //Case 2: Find contacts in group type - Access Control
317 [
318 'form_value' => ['group_type' => [$accessControlGT]],
319 'expected_count' => 1,
320 'expected_contact' => [$contact2],
321 ],
322 //Case 3: Find contacts in group type - Mailing List or Access List
323 [
324 'form_value' => ['group_type' => [$mailingListGT, $accessControlGT]],
325 'expected_count' => 2,
326 'expected_contact' => [$contact1, $contact2],
327 ],
328 ];
329
330 foreach ($useCases as $case) {
331 $query = new CRM_Contact_BAO_Query(CRM_Contact_BAO_Query::convertFormValues($case['form_value']));
332 list($select, $from, $where, $having) = $query->query();
333 $groupContacts = CRM_Core_DAO::executeQuery("SELECT DISTINCT contact_a.id, contact_a.first_name $from $where ORDER BY contact_a.first_name")->fetchAll();
334 foreach ($groupContacts as $key => $value) {
335 $groupContacts[$key] = $value['id'];
336 }
337 $this->assertEquals($case['expected_count'], count($groupContacts));
338 $this->checkArrayEquals($case['expected_contact'], $groupContacts);
339 }
340 }
341
342 }