Merge pull request #14283 from eileenmcnaughton/db_test3
[civicrm-core.git] / tests / phpunit / CRM / Contact / BAO / GroupTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
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_Group BAO
30 *
31 * @package CiviCRM
32 * @group headless
33 */
34 class CRM_Contact_BAO_GroupTest extends CiviUnitTestCase {
35
36 /**
37 * Sets up the fixture, for example, opens a network connection.
38 *
39 * This method is called before a test is executed.
40 */
41 protected function setUp() {
42 parent::setUp();
43 }
44
45 /**
46 * Tears down the fixture, for example, closes a network connection.
47 *
48 * This method is called after a test is executed.
49 */
50 protected function tearDown() {
51 $this->quickCleanup(array('civicrm_mapping_field', 'civicrm_mapping', 'civicrm_group', 'civicrm_saved_search'));
52 }
53
54 /**
55 * Test case for add( ).
56 */
57 public function testAddSimple() {
58
59 $checkParams = $params = array(
60 'title' => 'Group Uno',
61 'description' => 'Group One',
62 'visibility' => 'User and User Admin Only',
63 'is_active' => 1,
64 );
65
66 $group = CRM_Contact_BAO_Group::create($params);
67
68 $this->assertDBCompareValues(
69 'CRM_Contact_DAO_Group',
70 array('id' => $group->id),
71 $checkParams
72 );
73 }
74
75 /**
76 * Test case to ensure child group is present in the hierarchy
77 * if it has multiple parent groups and not all are disabled.
78 */
79 public function testGroupHirearchy() {
80 // Use-case :
81 // 1. Create two parent group A and B and disable B
82 // 2. Create a child group C
83 // 3. Ensure that Group C is present in the group hierarchy
84 $params = array(
85 'name' => uniqid(),
86 'title' => 'Parent Group A',
87 'description' => 'Parent Group One',
88 'visibility' => 'User and User Admin Only',
89 'is_active' => 1,
90 );
91 $group1 = CRM_Contact_BAO_Group::create($params);
92
93 $params = array_merge($params, array(
94 'name' => uniqid(),
95 'title' => 'Parent Group B',
96 'description' => 'Parent Group Two',
97 // disable
98 'is_active' => 0,
99 ));
100 $group2 = CRM_Contact_BAO_Group::create($params);
101
102 $params = array_merge($params, array(
103 'name' => uniqid(),
104 'title' => 'Child Group C',
105 'description' => 'Child Group C',
106 'parents' => array(
107 $group1->id => 1,
108 $group2->id => 1,
109 ),
110 ));
111 $group3 = CRM_Contact_BAO_Group::create($params);
112
113 $params = array(
114 $group1->id => 1,
115 $group3->id => 1,
116 );
117 $groupsHierarchy = CRM_Contact_BAO_Group::getGroupsHierarchy($params, NULL, '&nbsp;&nbsp;', TRUE);
118 // check if child group is present in the tree with formatted group title prepended with spacer '&nbsp;&nbsp;'
119 $this->assertEquals('&nbsp;&nbsp;Child Group C', $groupsHierarchy[$group3->id]);
120
121 // Disable parent group A and ensure that child group C is not present as both of its parent groups are disabled
122 $group1->is_active = 0;
123 $group1->save();
124 $groupsHierarchy = CRM_Contact_BAO_Group::getGroupsHierarchy($params, NULL, '&nbsp;&nbsp;', TRUE);
125 $this->assertFalse(array_key_exists($group3->id, $groupsHierarchy));
126 }
127
128 /**
129 * Test adding a smart group.
130 */
131 public function testAddSmart() {
132
133 $checkParams = $params = array(
134 'title' => 'Group Dos',
135 'description' => 'Group Two',
136 'visibility' => 'User and User Admin Only',
137 'is_active' => 1,
138 'formValues' => array('sort_name' => 'Adams'),
139 );
140
141 $group = CRM_Contact_BAO_Group::createSmartGroup($params);
142
143 unset($checkParams['formValues']);
144 $this->assertDBCompareValues(
145 'CRM_Contact_DAO_Group',
146 array('id' => $group->id),
147 $checkParams
148 );
149 }
150
151 /**
152 * Load all sql data sets & return an array of saved searches.
153 *
154 * @return array
155 */
156 public function dataProviderSavedSearch() {
157
158 $this->loadSavedSearches();
159 $results = CRM_Core_DAO::singleValueQuery('SELECT GROUP_CONCAT(id) FROM civicrm_group WHERE saved_search_id IS NOT NULL');
160 return array(explode(',', $results));
161 }
162
163 /**
164 * Load saved search sql files into the DB.
165 */
166 public function loadSavedSearches() {
167 foreach (glob(dirname(__FILE__) . "/SavedSearchDataSets/*.sql") as $file) {
168 CRM_Utils_File::sourceSQLFile(NULL, $file);
169 }
170 }
171
172 /**
173 * Check we can load smart groups based on config from 'real DBs' without fatal errors.
174 *
175 * Note that we are only testing lack of errors at this stage
176 * @todo - for some reason the data was getting truncated from the group table using dataprovider - would be preferable to get that working
177 * //@notdataProvider dataProviderSavedSearch
178 * //@notparam integer $groupID
179 *
180 * To add to this dataset do
181 *
182 * SET @groupID = x;
183 * SELECT mapping_id FROM civicrm_group g LEFT JOIN civicrm_saved_search s ON saved_search_id = s.id WHERE g.id = @groupID INTO @mappingID;
184 * SELECT * FROM civicrm_mapping WHERE id = @mappingID;
185 * SELECT * FROM civicrm_mapping_field WHERE mapping_id = @mappingID;
186 * SELECT * FROM civicrm_saved_search WHERE mapping_id = @mappingID;
187 * SELECT g.* FROM civicrm_saved_search s LEFT JOIN civicrm_group g ON g.saved_search_id = s.id WHERE mapping_id = @mappingID;
188 *
189 * Copy the output to a single sql file and place in the SavedSearchDataSets folder - use the group number as the prefix.
190 * Try to keep as much of the real world irregular glory as you can! Don't change the table ids to be number 1 as this can hide errors
191 */
192 public function testGroupData() {
193 $groups = $this->dataProviderSavedSearch();
194 foreach ($groups[0] as $groupID) {
195 $group = new CRM_Contact_BAO_Group();
196 $group->id = $groupID;
197 $group->find(TRUE);
198
199 CRM_Contact_BAO_GroupContactCache::load($group, TRUE);
200 }
201 }
202
203 /**
204 * Ensure that when updating a group with a linked organisation record even tho that record's id doesn't match the group id no db error is produced
205 */
206 public function testGroupUpdateWithOrganization() {
207 $params = array(
208 'name' => uniqid(),
209 'title' => 'Group A',
210 'description' => 'Group One',
211 'visibility' => 'User and User Admin Only',
212 'is_active' => 1,
213 );
214 $group1 = CRM_Contact_BAO_Group::create($params);
215
216 $domain1 = $this->callAPISuccess('Domain', 'get', ['id' => 1]);
217 $params2 = array(
218 'name' => uniqid(),
219 'title' => 'Group B',
220 'description' => 'Group Two',
221 'visibility' => 'User and User Admin Only',
222 'is_active' => 1,
223 'organization_id' => $domain1['values'][1]['contact_id'],
224 );
225 $group2 = CRM_Contact_BAO_Group::create($params2);
226
227 $domain2 = $this->callAPISuccess('Domain', 'get', ['id' => 2]);
228 $params3 = array(
229 'name' => uniqid(),
230 'title' => 'Group C',
231 'description' => 'Group Three',
232 'visibility' => 'User and User Admin Only',
233 'is_active' => 1,
234 'organization_id' => $domain2['values'][2]['contact_id'],
235 );
236 $group3 = CRM_Contact_BAO_Group::create($params3);
237 $params2['id'] = $group2->id;
238 $testUpdate = CRM_Contact_BAO_Group::create($params2);
239 }
240
241 /**
242 * Ensure that when hidden smart group is created, wildcard string value is not ignored
243 */
244 public function testHiddenSmartGroup() {
245 $customGroup = $this->customGroupCreate();
246 $fields = array(
247 'label' => 'testFld',
248 'data_type' => 'String',
249 'html_type' => 'Text',
250 'custom_group_id' => $customGroup['id'],
251 );
252 $customFieldID = CRM_Core_BAO_CustomField::create($fields)->id;
253
254 $contactID = $this->individualCreate(['custom_' . $customFieldID => 'abc']);
255
256 $hiddenSmartParams = [
257 'group_type' => ['2' => 1],
258 'form_values' => ['custom_' . $customFieldID => ['LIKE' => '%a%']],
259 'saved_search_id' => NULL,
260 'search_custom_id' => NULL,
261 'search_context' => 'advanced',
262 ];
263 list($smartGroupID, $savedSearchID) = CRM_Contact_BAO_Group::createHiddenSmartGroup($hiddenSmartParams);
264
265 $mailingID = $this->callAPISuccess('Mailing', 'create', [])['id'];
266 $this->callAPISuccess('MailingGroup', 'create', array(
267 'mailing_id' => $mailingID,
268 'group_type' => 'Include',
269 'entity_table' => 'civicrm_group',
270 'entity_id' => $smartGroupID,
271 ));
272
273 CRM_Mailing_BAO_Mailing::getRecipients($mailingID);
274 $recipients = $this->callAPISuccess('MailingRecipients', 'get', ['mailing_id' => $mailingID]);
275 $this->assertEquals(1, $recipients['count'], 'Check recipient count');
276 }
277
278 }