Commit | Line | Data |
---|---|---|
6a488035 | 1 | <?php |
0eea664b | 2 | |
6a488035 TO |
3 | /** |
4 | * Include dataProvider for tests | |
fb1ee468 | 5 | * |
acb109b7 | 6 | * @group headless |
6a488035 TO |
7 | */ |
8 | class CRM_Contact_BAO_QueryTest extends CiviUnitTestCase { | |
fb1ee468 | 9 | |
dbaa9d7d | 10 | use CRMTraits_Financial_FinancialACLTrait; |
faba82fc | 11 | use CRMTraits_Financial_PriceSetTrait; |
6a488035 | 12 | |
e9479dcf EM |
13 | /** |
14 | * @return CRM_Contact_BAO_QueryTestDataProvider | |
15 | */ | |
6a488035 | 16 | public function dataProvider() { |
acb1052e | 17 | return new CRM_Contact_BAO_QueryTestDataProvider(); |
6a488035 TO |
18 | } |
19 | ||
c69ecb12 | 20 | /** |
21 | * Clean up after test. | |
22 | * | |
23 | * @throws \Exception | |
24 | */ | |
594a9328 | 25 | public function tearDown(): void { |
faba82fc | 26 | $this->quickCleanUpFinancialEntities(); |
c69ecb12 | 27 | $tablesToTruncate = [ |
6a488035 TO |
28 | 'civicrm_group_contact', |
29 | 'civicrm_group', | |
30 | 'civicrm_saved_search', | |
31 | 'civicrm_entity_tag', | |
32 | 'civicrm_tag', | |
33 | 'civicrm_contact', | |
9b1e4469 | 34 | 'civicrm_address', |
c69ecb12 | 35 | ]; |
6a488035 | 36 | $this->quickCleanup($tablesToTruncate); |
673fae6c | 37 | parent::tearDown(); |
6a488035 TO |
38 | } |
39 | ||
40 | /** | |
3af96592 | 41 | * Test CRM_Contact_BAO_Query::searchQuery(). |
42 | * | |
6c6e6187 | 43 | * @dataProvider dataProvider |
3af96592 | 44 | * |
1e1fdcf6 EM |
45 | * @param $fv |
46 | * @param $count | |
47 | * @param $ids | |
8f36c0f5 | 48 | * |
49 | * @throws \CRM_Core_Exception | |
6a488035 | 50 | */ |
8f36c0f5 | 51 | public function testSearch($fv, $count, $ids) { |
c69ecb12 | 52 | $this->callAPISuccess('SavedSearch', 'create', ['form_values' => 'a:9:{s:5:"qfKey";s:32:"0123456789abcdef0123456789abcdef";s:13:"includeGroups";a:1:{i:0;s:1:"3";}s:13:"excludeGroups";a:0:{}s:11:"includeTags";a:0:{}s:11:"excludeTags";a:0:{}s:4:"task";s:2:"14";s:8:"radio_ts";s:6:"ts_all";s:14:"customSearchID";s:1:"4";s:17:"customSearchClass";s:36:"CRM_Contact_Form_Search_Custom_Group";}']); |
53 | $this->callAPISuccess('SavedSearch', 'create', ['form_values' => 'a:9:{s:5:"qfKey";s:32:"0123456789abcdef0123456789abcdef";s:13:"includeGroups";a:1:{i:0;s:1:"3";}s:13:"excludeGroups";a:0:{}s:11:"includeTags";a:0:{}s:11:"excludeTags";a:0:{}s:4:"task";s:2:"14";s:8:"radio_ts";s:6:"ts_all";s:14:"customSearchID";s:1:"4";s:17:"customSearchClass";s:36:"CRM_Contact_Form_Search_Custom_Group";}']); | |
54 | ||
55 | $tag7 = $this->ids['Tag'][7] = $this->tagCreate(['name' => 'Test Tag 7', 'description' => 'Test Tag 7'])['id']; | |
56 | $tag9 = $this->ids['Tag'][9] = $this->tagCreate(['name' => 'Test Tag 9', 'description' => 'Test Tag 9'])['id']; | |
fe128a5a MD |
57 | $tag10 = $this->ids['Tag'][10] = $this->tagCreate(['name' => 'Test Tag 10', 'description' => 'Test Tag 10', 'parent_id' => $tag9])['id']; |
58 | $tag11 = $this->ids['Tag'][11] = $this->tagCreate(['name' => 'Test Tag 11', 'description' => 'Test Tag 11', 'parent_id' => $tag10])['id']; | |
59 | ||
c69ecb12 | 60 | $groups = [ |
61 | 3 => ['name' => 'Test Group 3'], | |
62 | 4 => ['name' => 'Test Smart Group 4', 'saved_search_id' => 1], | |
63 | 5 => ['name' => 'Test Group 5'], | |
64 | 6 => ['name' => 'Test Smart Group 6', 'saved_search_id' => 2], | |
65 | ]; | |
66 | ||
67 | foreach ($groups as $id => $group) { | |
68 | $this->ids['Group'][$id] = $this->groupCreate(array_merge($group, ['title' => $group['name']])); | |
69 | } | |
70 | $individuals = [ | |
71 | ['first_name' => 'Test', 'last_name' => 'Test Contact 9', 'gender_id' => 1, 'prefix_id' => 1, 'suffix_id' => 1], | |
72 | ['first_name' => 'Test', 'last_name' => 'Test Contact 10', 'gender_id' => 2, 'prefix_id' => 2, 'suffix_id' => 2, 'api.entity_tag.create' => ['tag_id' => $tag9]], | |
73 | ['first_name' => 'Test', 'last_name' => 'Test Contact 11', 'gender_id' => 3, 'prefix_id' => 3, 'suffix_id' => 3, 'api.entity_tag.create' => ['tag_id' => $tag7]], | |
fb1ee468 | 74 | [ |
75 | 'first_name' => 'Test', | |
76 | 'last_name' => 'Test Contact 12', | |
77 | 'gender_id' => 3, | |
78 | 'prefix_id' => 4, | |
79 | 'suffix_id' => 4, | |
80 | 'api.entity_tag.create' => ['tag_id' => $tag9], | |
81 | 'api.entity_tag.create.2' => ['tag_id' => $tag7], | |
82 | ], | |
c69ecb12 | 83 | ['first_name' => 'Test', 'last_name' => 'Test Contact 13', 'gender_id' => 2, 'prefix_id' => 2, 'suffix_id' => 2], |
84 | ['first_name' => 'Test', 'last_name' => 'Test Contact 14', 'gender_id' => 3, 'prefix_id' => 4, 'suffix_id' => 4, 'api.entity_tag.create' => ['tag_id' => $tag9]], | |
85 | ['first_name' => 'Test', 'last_name' => 'Test Contact 15', 'gender_id' => 3, 'prefix_id' => 4, 'suffix_id' => 5, 'api.entity_tag.create' => ['tag_id' => $tag7]], | |
fb1ee468 | 86 | [ |
87 | 'first_name' => 'Test', | |
88 | 'last_name' => 'Test Contact 16', | |
89 | 'gender_id' => 3, | |
90 | 'prefix_id' => 4, | |
91 | 'suffix_id' => 6, | |
92 | 'api.entity_tag.create' => ['tag_id' => $tag9], | |
93 | 'api.entity_tag.create.2' => ['tag_id' => $tag7], | |
94 | ], | |
c69ecb12 | 95 | ['first_name' => 'Test', 'last_name' => 'Test Contact 17', 'gender_id' => 2, 'prefix_id' => 4, 'suffix_id' => 7], |
96 | ['first_name' => 'Test', 'last_name' => 'Test Contact 18', 'gender_id' => 2, 'prefix_id' => 4, 'suffix_id' => 4, 'api.entity_tag.create' => ['tag_id' => $tag9]], | |
97 | ['first_name' => 'Test', 'last_name' => 'Test Contact 19', 'gender_id' => 2, 'prefix_id' => 4, 'suffix_id' => 6, 'api.entity_tag.create.2' => ['tag_id' => $tag7]], | |
fb1ee468 | 98 | [ |
99 | 'first_name' => 'Test', | |
100 | 'last_name' => 'Test Contact 20', | |
101 | 'gender_id' => 1, | |
102 | 'prefix_id' => 4, | |
103 | 'suffix_id' => 6, | |
104 | 'api.entity_tag.create' => ['tag_id' => $tag9], | |
105 | 'api.entity_tag.create.2' => ['tag_id' => $tag7], | |
106 | ], | |
c69ecb12 | 107 | ['first_name' => 'Test', 'last_name' => 'Test Contact 21', 'gender_id' => 3, 'prefix_id' => 1, 'suffix_id' => 6], |
108 | ['first_name' => 'Test', 'last_name' => 'Test Contact 22', 'gender_id' => 1, 'prefix_id' => 1, 'suffix_id' => 1, 'api.entity_tag.create' => ['tag_id' => $tag9]], | |
109 | ['first_name' => 'Test', 'last_name' => 'Test Contact 23', 'gender_id' => 3, 'prefix_id' => 1, 'suffix_id' => 1, 'api.entity_tag.create' => ['tag_id' => $tag7]], | |
fb1ee468 | 110 | [ |
111 | 'first_name' => 'Test', | |
112 | 'last_name' => 'Test Contact 24', | |
113 | 'gender_id' => 3, | |
114 | 'prefix_id' => 3, | |
115 | 'suffix_id' => 2, | |
116 | 'api.entity_tag.create' => ['tag_id' => $tag9], | |
117 | 'api.entity_tag.create.2' => ['tag_id' => $tag7], | |
118 | ], | |
fe128a5a MD |
119 | ['first_name' => 'Test', 'last_name' => 'Test Contact 25', 'api.entity_tag.create' => ['tag_id' => $tag10]], |
120 | ['first_name' => 'Test', 'last_name' => 'Test Contact 26', 'api.entity_tag.create' => ['tag_id' => $tag11]], | |
c69ecb12 | 121 | ]; |
122 | foreach ($individuals as $individual) { | |
123 | $this->ids['Contact'][$individual['last_name']] = $this->individualCreate($individual); | |
124 | } | |
125 | $groupContacts = [ | |
126 | [5 => 13], | |
127 | [5 => 14], | |
128 | [5 => 15], | |
129 | [5 => 16], | |
130 | [5 => 21], | |
131 | [5 => 22], | |
132 | [5 => 23], | |
133 | [5 => 24], | |
134 | [3 => 17], | |
135 | [3 => 18], | |
136 | [3 => 19], | |
137 | [3 => 20], | |
138 | [3 => 21], | |
139 | [3 => 22], | |
140 | [3 => 23], | |
141 | [3 => 24], | |
142 | ]; | |
143 | foreach ($groupContacts as $group) { | |
144 | $groupID = $this->ids['Group'][key($group)]; | |
145 | $contactID = $this->ids['Contact']['Test Contact ' . reset($group)]; | |
146 | $this->callAPISuccess('GroupContact', 'create', ['group_id' => $groupID, 'contact_id' => $contactID, 'status' => 'Added']); | |
147 | } | |
148 | ||
149 | // We have migrated from a hard-coded dataset to a dynamic one but are still working with the same | |
150 | // dataprovider at this stage -> wrangle. | |
151 | foreach ($fv as $key => $value) { | |
152 | $entity = ucfirst($key); | |
153 | if (!array_key_exists($entity, $this->ids)) { | |
154 | continue; | |
155 | } | |
156 | if (is_numeric($value)) { | |
157 | $fv[$key] = $this->ids[$entity][$value]; | |
158 | } | |
159 | elseif (!empty($value[0])) { | |
160 | foreach ($value as $index => $oldGroup) { | |
161 | $fv[$key][$index] = $this->ids[$entity][$oldGroup]; | |
162 | } | |
163 | } | |
164 | else { | |
165 | foreach (array_keys($value) as $index) { | |
166 | unset($fv[$key][$index]); | |
167 | $fv[$key][$this->ids[$entity][$index]] = 1; | |
168 | } | |
169 | } | |
170 | } | |
6a488035 TO |
171 | |
172 | $params = CRM_Contact_BAO_Query::convertFormValues($fv); | |
92915c55 | 173 | $obj = new CRM_Contact_BAO_Query($params); |
b81f44dd | 174 | |
175 | // let's set useGroupBy=true since we are listing contacts here who might belong to | |
176 | // more than one group / tag / notes etc. | |
177 | $obj->_useGroupBy = TRUE; | |
178 | ||
92915c55 | 179 | $dao = $obj->searchQuery(); |
6a488035 | 180 | |
c69ecb12 | 181 | $contacts = []; |
6a488035 TO |
182 | while ($dao->fetch()) { |
183 | $contacts[] = $dao->contact_id; | |
184 | } | |
185 | ||
186 | sort($contacts, SORT_NUMERIC); | |
187 | ||
c69ecb12 | 188 | $expectedIDs = []; |
189 | foreach ($ids as $id) { | |
190 | $expectedIDs[] = $this->ids['Contact']['Test Contact ' . $id]; | |
191 | } | |
fe128a5a | 192 | |
c69ecb12 | 193 | $this->assertEquals($expectedIDs, $contacts); |
6a488035 | 194 | } |
e5fccefb EM |
195 | |
196 | /** | |
eceb18cc | 197 | * Check that we get a successful result querying for home address. |
e5fccefb | 198 | * CRM-14263 search builder failure with search profile & address in criteria |
8f36c0f5 | 199 | * |
200 | * @throws \CRM_Core_Exception | |
e5fccefb | 201 | */ |
00be9182 | 202 | public function testSearchProfileHomeCityCRM14263() { |
e5fccefb | 203 | $contactID = $this->individualCreate(); |
c26679b7 | 204 | Civi::settings()->set('defaultSearchProfileID', 1); |
fb1ee468 | 205 | $this->callAPISuccess('address', 'create', [ |
39b959db SL |
206 | 'contact_id' => $contactID, |
207 | 'city' => 'Cool City', | |
208 | 'location_type_id' => 1, | |
fb1ee468 | 209 | ]); |
210 | $params = [ | |
211 | 0 => [ | |
e5fccefb EM |
212 | 0 => 'city-1', |
213 | 1 => '=', | |
214 | 2 => 'Cool City', | |
215 | 3 => 1, | |
216 | 4 => 0, | |
fb1ee468 | 217 | ], |
218 | ]; | |
219 | $returnProperties = [ | |
e5fccefb EM |
220 | 'contact_type' => 1, |
221 | 'contact_sub_type' => 1, | |
222 | 'sort_name' => 1, | |
fb1ee468 | 223 | ]; |
e5fccefb EM |
224 | |
225 | $queryObj = new CRM_Contact_BAO_Query($params, $returnProperties); | |
226 | try { | |
63ae2e7b | 227 | $resultDAO = $queryObj->searchQuery(); |
55eb4e22 | 228 | $this->assertTrue($resultDAO->fetch()); |
e5fccefb | 229 | } |
55eb4e22 EM |
230 | catch (PEAR_Exception $e) { |
231 | $err = $e->getCause(); | |
c26679b7 | 232 | $this->fail('invalid SQL created' . $e->getMessage() . ' ' . $err->userinfo); |
e5fccefb | 233 | |
55eb4e22 | 234 | } |
e5fccefb EM |
235 | } |
236 | ||
55eb4e22 | 237 | /** |
eceb18cc | 238 | * Check that we get a successful result querying for home address. |
55eb4e22 | 239 | * CRM-14263 search builder failure with search profile & address in criteria |
8f36c0f5 | 240 | * |
241 | * @throws \CRM_Core_Exception | |
55eb4e22 | 242 | */ |
00be9182 | 243 | public function testSearchProfileHomeCityNoResultsCRM14263() { |
55eb4e22 | 244 | $contactID = $this->individualCreate(); |
c26679b7 | 245 | Civi::settings()->set('defaultSearchProfileID', 1); |
fb1ee468 | 246 | $this->callAPISuccess('address', 'create', [ |
39b959db SL |
247 | 'contact_id' => $contactID, |
248 | 'city' => 'Cool City', | |
249 | 'location_type_id' => 1, | |
fb1ee468 | 250 | ]); |
251 | $params = [ | |
252 | 0 => [ | |
55eb4e22 EM |
253 | 0 => 'city-1', |
254 | 1 => '=', | |
255 | 2 => 'Dumb City', | |
256 | 3 => 1, | |
257 | 4 => 0, | |
fb1ee468 | 258 | ], |
259 | ]; | |
260 | $returnProperties = [ | |
55eb4e22 EM |
261 | 'contact_type' => 1, |
262 | 'contact_sub_type' => 1, | |
263 | 'sort_name' => 1, | |
fb1ee468 | 264 | ]; |
55eb4e22 EM |
265 | |
266 | $queryObj = new CRM_Contact_BAO_Query($params, $returnProperties); | |
267 | try { | |
63ae2e7b | 268 | $resultDAO = $queryObj->searchQuery(); |
55eb4e22 EM |
269 | $this->assertFalse($resultDAO->fetch()); |
270 | } | |
271 | catch (PEAR_Exception $e) { | |
272 | $err = $e->getCause(); | |
c26679b7 | 273 | $this->fail('invalid SQL created' . $e->getMessage() . ' ' . $err->userinfo); |
55eb4e22 EM |
274 | |
275 | } | |
276 | } | |
92915c55 | 277 | |
b3e1c09d | 278 | /** |
a3fccfc7 | 279 | * Test searchPrimaryDetailsOnly setting. |
8f36c0f5 | 280 | * |
281 | * @throws \CRM_Core_Exception | |
b3e1c09d | 282 | */ |
9349bcf7 | 283 | public function testSearchPrimaryLocTypes() { |
b3e1c09d | 284 | $contactID = $this->individualCreate(); |
fb1ee468 | 285 | $params = [ |
b3e1c09d | 286 | 'contact_id' => $contactID, |
287 | 'email' => 'primary@example.com', | |
288 | 'is_primary' => 1, | |
fb1ee468 | 289 | ]; |
b3e1c09d | 290 | $this->callAPISuccess('email', 'create', $params); |
291 | ||
292 | unset($params['is_primary']); | |
293 | $params['email'] = 'secondary@team.com'; | |
294 | $this->callAPISuccess('email', 'create', $params); | |
295 | ||
fb1ee468 | 296 | foreach ([0, 1] as $searchPrimary) { |
a3fccfc7 | 297 | Civi::settings()->set('searchPrimaryDetailsOnly', $searchPrimary); |
b3e1c09d | 298 | |
fb1ee468 | 299 | $params = [ |
300 | 0 => [ | |
b3e1c09d | 301 | 0 => 'email', |
302 | 1 => 'LIKE', | |
c245fd99 | 303 | 2 => 'sEcondary@example.com', |
b3e1c09d | 304 | 3 => 0, |
305 | 4 => 1, | |
fb1ee468 | 306 | ], |
307 | ]; | |
308 | $returnProperties = [ | |
b3e1c09d | 309 | 'contact_type' => 1, |
310 | 'contact_sub_type' => 1, | |
311 | 'sort_name' => 1, | |
fb1ee468 | 312 | ]; |
b3e1c09d | 313 | |
314 | $queryObj = new CRM_Contact_BAO_Query($params, $returnProperties); | |
63ae2e7b | 315 | $resultDAO = $queryObj->searchQuery(); |
b3e1c09d | 316 | |
317 | if ($searchPrimary) { | |
318 | $this->assertEquals($resultDAO->N, 0); | |
319 | } | |
320 | else { | |
321 | //Assert secondary email gets included in search results. | |
322 | while ($resultDAO->fetch()) { | |
323 | $this->assertEquals('secondary@example.com', $resultDAO->email); | |
324 | } | |
325 | } | |
326 | ||
327 | // API should always return primary email. | |
fb1ee468 | 328 | $result = $this->callAPISuccess('Contact', 'get', ['contact_id' => $contactID]); |
b3e1c09d | 329 | $this->assertEquals('primary@example.com', $result['values'][$contactID]['email']); |
330 | } | |
331 | } | |
332 | ||
db1a73f5 KE |
333 | /** |
334 | * Test created to prove failure of search on state when location | |
335 | * display name is different form location name (issue 607) | |
8f36c0f5 | 336 | * |
337 | * @throws \CRM_Core_Exception | |
db1a73f5 KE |
338 | */ |
339 | public function testSearchOtherLocationUpperLower() { | |
340 | ||
341 | $params = [ | |
342 | 0 => [ | |
343 | 0 => 'state_province-4', | |
344 | 1 => 'IS NOT EMPTY', | |
345 | 2 => '', | |
346 | 3 => 1, | |
347 | 4 => 0, | |
348 | ], | |
349 | ]; | |
350 | $returnProperties = [ | |
351 | 'contact_type' => 1, | |
352 | 'contact_sub_type' => 1, | |
353 | 'sort_name' => 1, | |
354 | 'location' => [ | |
355 | 'other' => [ | |
356 | 'location_type' => 4, | |
357 | 'state_province' => 1, | |
358 | ], | |
359 | ], | |
360 | ]; | |
361 | ||
6f1ae9ee KE |
362 | // update with the api does not work because it updates both the name and the |
363 | // the display_name. Plain SQL however does the job | |
db1a73f5 KE |
364 | CRM_Core_DAO::executeQuery('update civicrm_location_type set name=%2 where id=%1', |
365 | [ | |
366 | 1 => [4, 'Integer'], | |
367 | 2 => ['other', 'String'], | |
368 | ]); | |
369 | ||
370 | $queryObj = new CRM_Contact_BAO_Query($params, $returnProperties); | |
371 | ||
63ae2e7b | 372 | $resultDAO = $queryObj->searchQuery(); |
db1a73f5 KE |
373 | $resultDAO->fetch(); |
374 | } | |
375 | ||
6c6e6187 | 376 | /** |
fea8ae41 | 377 | * CRM-14263 search builder failure with search profile & address in criteria. |
378 | * | |
6c6e6187 TO |
379 | * We are retrieving primary here - checking the actual sql seems super prescriptive - but since the massive query object has |
380 | * so few tests detecting any change seems good here :-) | |
fea8ae41 | 381 | * |
382 | * @dataProvider getSearchProfileData | |
383 | * | |
384 | * @param array $params | |
39b959db SL |
385 | * @param string $selectClause |
386 | * @param string $whereClause | |
fb1ee468 | 387 | * |
388 | * @throws \CRM_Core_Exception | |
6c6e6187 | 389 | */ |
fea8ae41 | 390 | public function testSearchProfilePrimaryCityCRM14263($params, $selectClause, $whereClause) { |
6c6e6187 | 391 | $contactID = $this->individualCreate(); |
c26679b7 | 392 | Civi::settings()->set('defaultSearchProfileID', 1); |
fb1ee468 | 393 | $this->callAPISuccess('address', 'create', [ |
39b959db SL |
394 | 'contact_id' => $contactID, |
395 | 'city' => 'Cool CITY', | |
396 | 'street_address' => 'Long STREET', | |
397 | 'location_type_id' => 1, | |
fb1ee468 | 398 | ]); |
399 | $returnProperties = [ | |
92915c55 TO |
400 | 'contact_type' => 1, |
401 | 'contact_sub_type' => 1, | |
402 | 'sort_name' => 1, | |
fb1ee468 | 403 | ]; |
99827266 | 404 | $expectedSQL = 'SELECT contact_a.id as contact_id, contact_a.contact_type as `contact_type`, contact_a.contact_sub_type as `contact_sub_type`, contact_a.sort_name as `sort_name`, civicrm_address.id as address_id, ' . $selectClause . " FROM civicrm_contact contact_a LEFT JOIN civicrm_address ON ( contact_a.id = civicrm_address.contact_id AND civicrm_address.is_primary = 1 ) WHERE ( ( " . $whereClause . " ) ) AND ( 1 ) AND (contact_a.is_deleted = 0) ORDER BY `contact_a`.`sort_name` ASC, `contact_a`.`id` "; |
6c6e6187 TO |
405 | $queryObj = new CRM_Contact_BAO_Query($params, $returnProperties); |
406 | try { | |
299c1530 | 407 | $this->assertLike($expectedSQL, $queryObj->getSearchSQL()); |
fea8ae41 | 408 | list($select, $from, $where, $having) = $queryObj->query(); |
409 | $dao = CRM_Core_DAO::executeQuery("$select $from $where $having"); | |
410 | $dao->fetch(); | |
411 | $this->assertEquals('Anderson, Anthony', $dao->sort_name); | |
6c6e6187 TO |
412 | } |
413 | catch (PEAR_Exception $e) { | |
414 | $err = $e->getCause(); | |
c26679b7 | 415 | $this->fail('invalid SQL created' . $e->getMessage() . ' ' . $err->userinfo); |
55eb4e22 | 416 | |
55eb4e22 | 417 | } |
6c6e6187 | 418 | } |
96025800 | 419 | |
fea8ae41 | 420 | /** |
421 | * Get data sets to test for search. | |
422 | */ | |
423 | public function getSearchProfileData() { | |
424 | return [ | |
425 | [ | |
fb1ee468 | 426 | [['city', '=', 'Cool City', 1, 0]], |
c26679b7 | 427 | 'civicrm_address.city as `city`', |
fb1ee468 | 428 | "civicrm_address.city = 'Cool City'", |
fea8ae41 | 429 | ], |
430 | [ | |
431 | // Note that in the query 'long street' is lower cased. We eventually want to change that & not mess with the vars - it turns out | |
432 | // it doesn't work on some charsets. However, the the lcasing affects more vars & we are looking to stagger removal of lcasing 'in case' | |
433 | // (although we have been removing without blowback since 2017) | |
fb1ee468 | 434 | [['street_address', '=', 'Long Street', 1, 0]], |
c26679b7 | 435 | 'civicrm_address.street_address as `street_address`', |
fb1ee468 | 436 | "civicrm_address.street_address LIKE '%Long Street%'", |
fea8ae41 | 437 | ], |
438 | ]; | |
439 | } | |
440 | ||
fd11fc34 | 441 | /** |
442 | * Test similarly handled activity fields qill and where clauses. | |
443 | * | |
444 | * @throws \CRM_Core_Exception | |
445 | */ | |
446 | public function testSearchBuilderActivityType() { | |
447 | $queryObj = new CRM_Contact_BAO_Query([['activity_type', '=', '3', 1, 0]]); | |
275686a3 | 448 | $this->assertStringContainsString('WHERE ( ( civicrm_activity.activity_type_id = 3 )', $queryObj->getSearchSQL()); |
fd11fc34 | 449 | $this->assertEquals('Activity Type = Email', $queryObj->_qill[1][0]); |
450 | ||
451 | $queryObj = new CRM_Contact_BAO_Query([['activity_type_id', '=', '3', 1, 0]]); | |
275686a3 | 452 | $this->assertStringContainsString('WHERE ( ( civicrm_activity.activity_type_id = 3 )', $queryObj->getSearchSQL()); |
fd11fc34 | 453 | $this->assertEquals('Activity Type ID = Email', $queryObj->_qill[1][0]); |
454 | ||
455 | $queryObj = new CRM_Contact_BAO_Query([['activity_status', '=', '3', 1, 0]]); | |
275686a3 | 456 | $this->assertStringContainsString('WHERE ( ( civicrm_activity.status_id = 3 )', $queryObj->getSearchSQL()); |
fd11fc34 | 457 | $this->assertEquals('Activity Status = Cancelled', $queryObj->_qill[1][0]); |
458 | ||
459 | $queryObj = new CRM_Contact_BAO_Query([['activity_status_id', '=', '3', 1, 0]]); | |
275686a3 | 460 | $this->assertStringContainsString('WHERE ( ( civicrm_activity.status_id = 3 )', $queryObj->getSearchSQL()); |
fd11fc34 | 461 | $this->assertEquals('Activity Status = Cancelled', $queryObj->_qill[1][0]); |
462 | ||
463 | $queryObj = new CRM_Contact_BAO_Query([['activity_engagement_level', '=', '3', 1, 0]]); | |
275686a3 | 464 | $this->assertStringContainsString('WHERE ( ( civicrm_activity.engagement_level = 3 )', $queryObj->getSearchSQL()); |
fd11fc34 | 465 | $this->assertEquals('Engagement Index = 3', $queryObj->_qill[1][0]); |
466 | ||
467 | $queryObj = new CRM_Contact_BAO_Query([['activity_id', '=', '3', 1, 0]]); | |
275686a3 | 468 | $this->assertStringContainsString('WHERE ( ( civicrm_activity.id = 3 )', $queryObj->getSearchSQL()); |
fd11fc34 | 469 | $this->assertEquals('Activity ID = 3', $queryObj->_qill[1][0]); |
470 | ||
471 | $queryObj = new CRM_Contact_BAO_Query([['activity_campaign_id', '=', '3', 1, 0]]); | |
275686a3 | 472 | $this->assertStringContainsString('WHERE ( ( civicrm_activity.campaign_id = 3 )', $queryObj->getSearchSQL()); |
281b62a7 | 473 | $this->assertEquals('Campaign ID = 3', $queryObj->_qill[1][0]); |
fd11fc34 | 474 | |
475 | $queryObj = new CRM_Contact_BAO_Query([['activity_priority_id', '=', '3', 1, 0]]); | |
275686a3 | 476 | $this->assertStringContainsString('WHERE ( ( civicrm_activity.priority_id = 3 )', $queryObj->getSearchSQL()); |
fd11fc34 | 477 | $this->assertEquals('Priority = Low', $queryObj->_qill[1][0]); |
478 | ||
479 | $queryObj = new CRM_Contact_BAO_Query([['activity_subject', '=', '3', 1, 0]]); | |
275686a3 | 480 | $this->assertStringContainsString("WHERE ( ( civicrm_activity.subject = '3' )", $queryObj->getSearchSQL()); |
fd11fc34 | 481 | $this->assertEquals("Subject = '3'", $queryObj->_qill[1][0]); |
482 | } | |
483 | ||
82ae55f4 | 484 | /** |
485 | * Test set up to test calling the query object per GroupContactCache BAO usage. | |
486 | * | |
487 | * CRM-17254 ensure that if only the contact_id is required other fields should | |
488 | * not be appended. | |
fd11fc34 | 489 | * |
490 | * @throws \CRM_Core_Exception | |
82ae55f4 | 491 | */ |
492 | public function testGroupContactCacheAddSearch() { | |
fb1ee468 | 493 | $returnProperties = ['contact_id']; |
494 | $params = [['group', 'IN', [1], 0, 0]]; | |
82ae55f4 | 495 | |
496 | $query = new CRM_Contact_BAO_Query( | |
497 | $params, $returnProperties, | |
498 | NULL, TRUE, FALSE, 1, | |
499 | TRUE, | |
500 | TRUE, FALSE | |
501 | ); | |
502 | ||
c26679b7 | 503 | list($select) = $query->query(); |
82ae55f4 | 504 | $this->assertEquals('SELECT contact_a.id as contact_id', $select); |
505 | } | |
506 | ||
9b1e4469 | 507 | /** |
508 | * Test smart groups with non-numeric don't fail on range queries. | |
509 | * | |
0e480632 | 510 | * @see https://issues.civicrm.org/jira/browse/CRM-14720 |
8f36c0f5 | 511 | * |
512 | * @throws \CRM_Core_Exception | |
9b1e4469 | 513 | */ |
514 | public function testNumericPostal() { | |
91c164ed | 515 | // Precaution as hitting some inconsistent set up running in isolation vs in the suite. |
516 | CRM_Core_DAO::executeQuery('UPDATE civicrm_address SET postal_code = NULL'); | |
517 | ||
fb1ee468 | 518 | $this->individualCreate(['api.address.create' => ['postal_code' => 5, 'location_type_id' => 'Main']]); |
519 | $this->individualCreate(['api.address.create' => ['postal_code' => 'EH10 4RB-889', 'location_type_id' => 'Main']]); | |
520 | $this->individualCreate(['api.address.create' => ['postal_code' => '4', 'location_type_id' => 'Main']]); | |
521 | $this->individualCreate(['api.address.create' => ['postal_code' => '6', 'location_type_id' => 'Main']]); | |
522 | $this->individualCreate(['api.address.create' => ['street_address' => 'just a street', 'location_type_id' => 'Main']]); | |
523 | $this->individualCreate(['api.address.create' => ['postal_code' => '12345678444455555555555555555555555555555555551314151617181920', 'location_type_id' => 'Main']]); | |
9b1e4469 | 524 | |
fb1ee468 | 525 | $params = [['postal_code_low', '=', 5, 0, 0]]; |
9b1e4469 | 526 | CRM_Contact_BAO_Query::convertFormValues($params); |
527 | ||
528 | $query = new CRM_Contact_BAO_Query( | |
fb1ee468 | 529 | $params, ['contact_id'], |
9b1e4469 | 530 | NULL, TRUE, FALSE, 1, |
531 | TRUE, | |
532 | TRUE, FALSE | |
533 | ); | |
534 | ||
c26679b7 | 535 | $sql = $query->query(); |
9b1e4469 | 536 | $result = CRM_Core_DAO::executeQuery(implode(' ', $sql)); |
537 | $this->assertEquals(2, $result->N); | |
538 | ||
539 | // We save this as a smart group and then load it. With mysql warnings on & CRM-14720 this | |
540 | // results in mysql warnings & hence fatal errors. | |
541 | /// I was unable to get mysql warnings to activate in the context of the unit tests - but | |
542 | // felt this code still provided a useful bit of coverage as it runs the various queries to load | |
543 | // the group & could generate invalid sql if a bug were introduced. | |
fb1ee468 | 544 | $groupParams = ['title' => 'postal codes', 'formValues' => $params, 'is_active' => 1]; |
9b1e4469 | 545 | $group = CRM_Contact_BAO_Group::createSmartGroup($groupParams); |
4f39b1e6 | 546 | CRM_Contact_BAO_GroupContactCache::load($group); |
9b1e4469 | 547 | } |
548 | ||
30415e03 | 549 | /** |
550 | * Test searches are case insensitive. | |
8f36c0f5 | 551 | * |
552 | * @throws \CRM_Core_Exception | |
30415e03 | 553 | */ |
554 | public function testCaseInsensitive() { | |
fb1ee468 | 555 | $orgID = $this->organizationCreate(['organization_name' => 'BOb']); |
556 | $params = [ | |
1809f3cf | 557 | 'display_name' => 'Minnie Mouse', |
558 | 'first_name' => 'Minnie', | |
559 | 'last_name' => 'Mouse', | |
560 | 'employer_id' => $orgID, | |
561 | 'contact_type' => 'Individual', | |
562 | 'nick_name' => 'Mins', | |
fb1ee468 | 563 | ]; |
1809f3cf | 564 | $this->callAPISuccess('Contact', 'create', $params); |
565 | unset($params['contact_type']); | |
566 | foreach ($params as $key => $value) { | |
8f36c0f5 | 567 | if ($key === 'employer_id') { |
fb1ee468 | 568 | $searchParams = [['current_employer', '=', 'bob', 0, 1]]; |
1809f3cf | 569 | } |
570 | else { | |
fb1ee468 | 571 | $searchParams = [[$key, '=', strtolower($value), 0, 1]]; |
1809f3cf | 572 | } |
8f36c0f5 | 573 | |
676a6ff4 | 574 | [$result] = CRM_Contact_BAO_Query::apiQuery($searchParams); |
575 | $this->assertCount(1, $result, 'search for ' . $key); | |
576 | $contact = reset($result); | |
1809f3cf | 577 | $this->assertEquals('Minnie Mouse', $contact['display_name']); |
578 | $this->assertEquals('BOb', $contact['current_employer']); | |
579 | } | |
30415e03 | 580 | } |
581 | ||
9a1491bb | 582 | /** |
583 | * Test smart groups with non-numeric don't fail on equal queries. | |
584 | * | |
0e480632 | 585 | * @see https://issues.civicrm.org/jira/browse/CRM-14720 |
8f36c0f5 | 586 | * |
587 | * @throws \CRM_Core_Exception | |
9a1491bb | 588 | */ |
589 | public function testNonNumericEqualsPostal() { | |
fb1ee468 | 590 | $this->individualCreate(['api.address.create' => ['postal_code' => 5, 'location_type_id' => 'Main']]); |
591 | $this->individualCreate(['api.address.create' => ['postal_code' => 'EH10 4RB-889', 'location_type_id' => 'Main']]); | |
592 | $this->individualCreate(['api.address.create' => ['postal_code' => '4', 'location_type_id' => 'Main']]); | |
593 | $this->individualCreate(['api.address.create' => ['postal_code' => '6', 'location_type_id' => 'Main']]); | |
9a1491bb | 594 | |
fb1ee468 | 595 | $params = [['postal_code', '=', 'EH10 4RB-889', 0, 0]]; |
9a1491bb | 596 | CRM_Contact_BAO_Query::convertFormValues($params); |
597 | ||
598 | $query = new CRM_Contact_BAO_Query( | |
fb1ee468 | 599 | $params, ['contact_id'], |
9a1491bb | 600 | NULL, TRUE, FALSE, 1, |
601 | TRUE, | |
602 | TRUE, FALSE | |
603 | ); | |
604 | ||
605 | $sql = $query->query(FALSE); | |
2fc64082 | 606 | $this->assertEquals("WHERE ( civicrm_address.postal_code = 'EH10 4RB-889' ) AND (contact_a.is_deleted = 0)", $sql[2]); |
9a1491bb | 607 | $result = CRM_Core_DAO::executeQuery(implode(' ', $sql)); |
608 | $this->assertEquals(1, $result->N); | |
609 | ||
610 | } | |
611 | ||
8f36c0f5 | 612 | /** |
613 | * Test relationship description. | |
614 | * | |
615 | * @throws \CRM_Core_Exception | |
616 | */ | |
6e83b317 CW |
617 | public function testRelationshipDescription() { |
618 | $relType = $this->callAPISuccess('RelationshipType', 'create', [ | |
8f36c0f5 | 619 | 'name_a_b' => 'blah', |
620 | 'name_b_a' => 'other blah', | |
6e83b317 CW |
621 | ]); |
622 | $contactID_a = $this->individualCreate([], 1); | |
623 | $contactID_b = $this->individualCreate([], 2); | |
624 | $contactID_c = $this->individualCreate([], 3); | |
625 | $contactID_d = $this->individualCreate([], 4); | |
626 | $desc = uniqid('rel', TRUE); | |
627 | $this->callAPISuccess('Relationship', 'create', [ | |
628 | 'contact_id_a' => $contactID_a, | |
629 | 'contact_id_b' => $contactID_b, | |
630 | 'relationship_type_id' => $relType['id'], | |
631 | 'is_active' => 1, | |
632 | 'description' => $desc, | |
633 | ]); | |
634 | $this->callAPISuccess('Relationship', 'create', [ | |
635 | 'contact_id_a' => $contactID_c, | |
636 | 'contact_id_b' => $contactID_d, | |
637 | 'relationship_type_id' => $relType['id'], | |
638 | 'is_active' => 1, | |
639 | 'description' => 'nothing of interest', | |
640 | ]); | |
641 | $params = [ | |
642 | ['relation_description', '=', substr($desc, 3, 18), 0, 0], | |
643 | ]; | |
644 | ||
645 | $query = new CRM_Contact_BAO_Query($params); | |
646 | $dao = $query->searchQuery(); | |
647 | // This is a little weird but seems consistent with the behavior of the search form in general. | |
648 | // Technically there are 2 contacts who share a relationship with the description searched for, | |
649 | // so one might expect the search form to return both of them instead of just Contact A... but it doesn't. | |
8f36c0f5 | 650 | $this->assertEquals('1', $dao->N, 'Search query returns exactly 1 result?'); |
651 | $this->assertTrue($dao->fetch(), 'Search query returns success?'); | |
652 | $this->assertEquals($contactID_a, $dao->contact_id, 'Search query returns contact A?'); | |
6e83b317 CW |
653 | } |
654 | ||
8f36c0f5 | 655 | /** |
656 | * Test non-reciprocal relationship. | |
657 | * | |
658 | * @throws \CRM_Core_Exception | |
659 | */ | |
72a2eeab AS |
660 | public function testNonReciprocalRelationshipTargetGroupIsCorrectResults() { |
661 | $contactID_a = $this->individualCreate(); | |
662 | $contactID_b = $this->individualCreate(); | |
fb1ee468 | 663 | $this->callAPISuccess('Relationship', 'create', [ |
72a2eeab AS |
664 | 'contact_id_a' => $contactID_a, |
665 | 'contact_id_b' => $contactID_b, | |
666 | 'relationship_type_id' => 1, | |
667 | 'is_active' => 1, | |
fb1ee468 | 668 | ]); |
72a2eeab AS |
669 | // Create a group and add contact A to it. |
670 | $groupID = $this->groupCreate(); | |
fb1ee468 | 671 | $this->callAPISuccess('GroupContact', 'create', ['group_id' => $groupID, 'contact_id' => $contactID_a, 'status' => 'Added']); |
72a2eeab AS |
672 | |
673 | // Add another (sans-relationship) contact to the group, | |
674 | $contactID_c = $this->individualCreate(); | |
fb1ee468 | 675 | $this->callAPISuccess('GroupContact', 'create', ['group_id' => $groupID, 'contact_id' => $contactID_c, 'status' => 'Added']); |
72a2eeab | 676 | |
fb1ee468 | 677 | $params = [ |
678 | [ | |
72a2eeab AS |
679 | 0 => 'relation_type_id', |
680 | 1 => 'IN', | |
681 | 2 => | |
fb1ee468 | 682 | [ |
683 | 0 => '1_b_a', | |
684 | ], | |
72a2eeab AS |
685 | 3 => 0, |
686 | 4 => 0, | |
fb1ee468 | 687 | ], |
688 | [ | |
72a2eeab AS |
689 | 0 => 'relation_target_group', |
690 | 1 => 'IN', | |
691 | 2 => | |
fb1ee468 | 692 | [ |
693 | 0 => $groupID, | |
694 | ], | |
72a2eeab AS |
695 | 3 => 0, |
696 | 4 => 0, | |
fb1ee468 | 697 | ], |
698 | ]; | |
72a2eeab AS |
699 | |
700 | $query = new CRM_Contact_BAO_Query($params); | |
701 | $dao = $query->searchQuery(); | |
c26679b7 | 702 | $this->assertEquals('1', $dao->N, 'Search query returns exactly 1 result?'); |
703 | $this->assertTrue($dao->fetch(), 'Search query returns success?'); | |
704 | $this->assertEquals($contactID_b, $dao->contact_id, 'Search query returns parent of contact A?'); | |
72a2eeab AS |
705 | } |
706 | ||
804261ab JP |
707 | /** |
708 | * Relationship search with custom fields. | |
c26679b7 | 709 | * |
710 | * @throws \CRM_Core_Exception | |
804261ab JP |
711 | */ |
712 | public function testReciprocalRelationshipWithCustomFields() { | |
713 | $params = [ | |
714 | 'extends' => 'Relationship', | |
715 | ]; | |
716 | $customGroup = $this->customGroupCreate($params); | |
717 | $customFieldId = $this->customFieldCreate(['custom_group_id' => $customGroup['id']])['id']; | |
718 | $contactID_a = $this->individualCreate(); | |
719 | $contactID_b = $this->individualCreate(); | |
720 | $relationship = $this->callAPISuccess('Relationship', 'create', [ | |
721 | 'contact_id_a' => $contactID_a, | |
722 | 'contact_id_b' => $contactID_b, | |
723 | 'relationship_type_id' => 2, | |
724 | 'is_active' => 1, | |
725 | "custom_{$customFieldId}" => 'testvalue', | |
726 | ]); | |
727 | $params = [ | |
728 | [ | |
729 | 0 => 'relation_type_id', | |
730 | 1 => 'IN', | |
731 | 2 => | |
732 | [ | |
733 | 0 => '2_a_b', | |
734 | ], | |
735 | 3 => 0, | |
736 | 4 => 0, | |
737 | ], | |
738 | [ | |
739 | 0 => "custom_{$customFieldId}", | |
740 | 1 => '=', | |
741 | 2 => 'testvalue', | |
742 | 3 => 0, | |
743 | 4 => 0, | |
744 | ], | |
745 | ]; | |
746 | ||
747 | $query = new CRM_Contact_BAO_Query($params); | |
748 | $dao = $query->searchQuery(); | |
749 | $this->assertEquals('2', $dao->N); | |
750 | $this->callAPISuccess('Relationship', 'delete', ['id' => $relationship['id']]); | |
751 | $this->callAPISuccess('Contact', 'delete', ['id' => $contactID_a, 'skip_undelete' => 1]); | |
752 | $this->callAPISuccess('Contact', 'delete', ['id' => $contactID_b, 'skip_undelete' => 1]); | |
753 | $this->callAPISuccess('CustomField', 'delete', ['id' => $customFieldId, 'skip_undelete' => 1]); | |
754 | $this->callAPISuccess('CustomGroup', 'delete', ['id' => $customGroup]); | |
755 | } | |
756 | ||
fb1ee468 | 757 | /** |
758 | * @throws \CRM_Core_Exception | |
759 | */ | |
72a2eeab AS |
760 | public function testReciprocalRelationshipTargetGroupIsCorrectResults() { |
761 | $contactID_a = $this->individualCreate(); | |
762 | $contactID_b = $this->individualCreate(); | |
fb1ee468 | 763 | $this->callAPISuccess('Relationship', 'create', [ |
72a2eeab AS |
764 | 'contact_id_a' => $contactID_a, |
765 | 'contact_id_b' => $contactID_b, | |
766 | 'relationship_type_id' => 2, | |
767 | 'is_active' => 1, | |
fb1ee468 | 768 | ]); |
72a2eeab AS |
769 | // Create a group and add contact A to it. |
770 | $groupID = $this->groupCreate(); | |
fb1ee468 | 771 | $this->callAPISuccess('GroupContact', 'create', ['group_id' => $groupID, 'contact_id' => $contactID_a, 'status' => 'Added']); |
72a2eeab AS |
772 | |
773 | // Add another (sans-relationship) contact to the group, | |
774 | $contactID_c = $this->individualCreate(); | |
fb1ee468 | 775 | $this->callAPISuccess('GroupContact', 'create', ['group_id' => $groupID, 'contact_id' => $contactID_c, 'status' => 'Added']); |
72a2eeab | 776 | |
fb1ee468 | 777 | $params = [ |
778 | [ | |
72a2eeab AS |
779 | 0 => 'relation_type_id', |
780 | 1 => 'IN', | |
781 | 2 => | |
fb1ee468 | 782 | [ |
783 | 0 => '2_a_b', | |
784 | ], | |
72a2eeab AS |
785 | 3 => 0, |
786 | 4 => 0, | |
fb1ee468 | 787 | ], |
788 | [ | |
72a2eeab AS |
789 | 0 => 'relation_target_group', |
790 | 1 => 'IN', | |
791 | 2 => | |
fb1ee468 | 792 | [ |
793 | 0 => $groupID, | |
794 | ], | |
72a2eeab AS |
795 | 3 => 0, |
796 | 4 => 0, | |
fb1ee468 | 797 | ], |
798 | ]; | |
72a2eeab AS |
799 | |
800 | $query = new CRM_Contact_BAO_Query($params); | |
801 | $dao = $query->searchQuery(); | |
c26679b7 | 802 | $this->assertEquals('1', $dao->N, 'Search query returns exactly 1 result?'); |
803 | $this->assertTrue($dao->fetch(), 'Search query returns success?'); | |
804 | $this->assertEquals($contactID_b, $dao->contact_id, 'Search query returns spouse of contact A?'); | |
72a2eeab AS |
805 | } |
806 | ||
c26679b7 | 807 | /** |
808 | * Test correct temporary table in reciprocal relationship search. | |
809 | * | |
810 | * @throws \CRM_Core_Exception | |
811 | */ | |
72a2eeab AS |
812 | public function testReciprocalRelationshipTargetGroupUsesTempTable() { |
813 | $groupID = $this->groupCreate(); | |
fb1ee468 | 814 | $params = [ |
815 | [ | |
72a2eeab AS |
816 | 0 => 'relation_type_id', |
817 | 1 => 'IN', | |
818 | 2 => | |
fb1ee468 | 819 | [ |
820 | 0 => '2_a_b', | |
821 | ], | |
72a2eeab AS |
822 | 3 => 0, |
823 | 4 => 0, | |
fb1ee468 | 824 | ], |
825 | [ | |
72a2eeab AS |
826 | 0 => 'relation_target_group', |
827 | 1 => 'IN', | |
828 | 2 => | |
fb1ee468 | 829 | [ |
830 | 0 => $groupID, | |
831 | ], | |
72a2eeab AS |
832 | 3 => 0, |
833 | 4 => 0, | |
fb1ee468 | 834 | ], |
835 | ]; | |
72a2eeab | 836 | $sql = CRM_Contact_BAO_Query::getQuery($params); |
275686a3 | 837 | $this->assertStringContainsStringIgnoringCase('INNER JOIN civicrm_tmp_e', $sql, 'Query appears to use temporary table of compiled relationships?'); |
72a2eeab AS |
838 | } |
839 | ||
8f36c0f5 | 840 | /** |
841 | * Test relationship permission clause. | |
842 | * | |
843 | * @throws \CRM_Core_Exception | |
844 | */ | |
9c9908e9 | 845 | public function testRelationshipPermissionClause() { |
846 | $params = [['relation_type_id', 'IN', ['1_b_a'], 0, 0], ['relation_permission', 'IN', [2], 0, 0]]; | |
847 | $sql = CRM_Contact_BAO_Query::getQuery($params); | |
275686a3 | 848 | $this->assertStringContainsString('(civicrm_relationship.is_permission_a_b IN (2))', $sql); |
9c9908e9 | 849 | } |
850 | ||
5ad36be5 SL |
851 | /** |
852 | * Test Relationship Clause | |
0e1544e7 | 853 | * |
854 | * @throws \CRM_Core_Exception | |
5ad36be5 SL |
855 | */ |
856 | public function testRelationshipClause() { | |
857 | $today = date('Ymd'); | |
c26679b7 | 858 | $from1 = ' FROM civicrm_contact contact_a LEFT JOIN civicrm_relationship ON (civicrm_relationship.contact_id_a = contact_a.id ) LEFT JOIN civicrm_contact contact_b ON (civicrm_relationship.contact_id_b = contact_b.id )'; |
859 | $from2 = ' FROM civicrm_contact contact_a LEFT JOIN civicrm_relationship ON (civicrm_relationship.contact_id_b = contact_a.id ) LEFT JOIN civicrm_contact contact_b ON (civicrm_relationship.contact_id_a = contact_b.id )'; | |
5ad36be5 SL |
860 | $where1 = "WHERE ( ( |
861 | civicrm_relationship.is_active = 1 AND | |
862 | ( civicrm_relationship.end_date IS NULL OR civicrm_relationship.end_date >= {$today} ) AND | |
863 | ( civicrm_relationship.start_date IS NULL OR civicrm_relationship.start_date <= {$today} ) | |
864 | ) AND (contact_b.is_deleted = 0) AND civicrm_relationship.relationship_type_id IN (8) ) AND (contact_a.is_deleted = 0)"; | |
865 | $where2 = "WHERE ( ( | |
866 | civicrm_relationship.is_active = 1 AND | |
867 | ( civicrm_relationship.end_date IS NULL OR civicrm_relationship.end_date >= {$today} ) AND | |
868 | ( civicrm_relationship.start_date IS NULL OR civicrm_relationship.start_date <= {$today} ) | |
869 | ) AND (contact_b.is_deleted = 0) AND civicrm_relationship.relationship_type_id IN (8,10) ) AND (contact_a.is_deleted = 0)"; | |
870 | // Test Traditional single select format | |
fb1ee468 | 871 | $params1 = [['relation_type_id', '=', '8_a_b', 0, 0]]; |
5ad36be5 | 872 | $query1 = new CRM_Contact_BAO_Query( |
fb1ee468 | 873 | $params1, ['contact_id'], |
5ad36be5 SL |
874 | NULL, TRUE, FALSE, 1, |
875 | TRUE, | |
876 | TRUE, FALSE | |
877 | ); | |
c26679b7 | 878 | $sql1 = $query1->query(); |
299c1530 | 879 | $this->assertLike($from1, $sql1[1]); |
880 | $this->assertLike($where1, $sql1[2]); | |
5ad36be5 | 881 | // Test single relationship type selected in multiple select. |
fb1ee468 | 882 | $params2 = [['relation_type_id', 'IN', ['8_a_b'], 0, 0]]; |
5ad36be5 | 883 | $query2 = new CRM_Contact_BAO_Query( |
fb1ee468 | 884 | $params2, ['contact_id'], |
5ad36be5 SL |
885 | NULL, TRUE, FALSE, 1, |
886 | TRUE, | |
887 | TRUE, FALSE | |
888 | ); | |
889 | $sql2 = $query2->query(FALSE); | |
299c1530 | 890 | $this->assertLike($from1, $sql2[1]); |
891 | $this->assertLike($where1, $sql2[2]); | |
5ad36be5 | 892 | // Test multiple relationship types selected. |
fb1ee468 | 893 | $params3 = [['relation_type_id', 'IN', ['8_a_b', '10_a_b'], 0, 0]]; |
5ad36be5 | 894 | $query3 = new CRM_Contact_BAO_Query( |
fb1ee468 | 895 | $params3, ['contact_id'], |
5ad36be5 SL |
896 | NULL, TRUE, FALSE, 1, |
897 | TRUE, | |
898 | TRUE, FALSE | |
899 | ); | |
900 | $sql3 = $query3->query(FALSE); | |
299c1530 | 901 | $this->assertLike($from1, $sql3[1]); |
902 | $this->assertLike($where2, $sql3[2]); | |
5ad36be5 | 903 | // Test Multiple Relationship type selected where one doesn't actually exist. |
fb1ee468 | 904 | $params4 = [['relation_type_id', 'IN', ['8_a_b', '10_a_b', '14_a_b'], 0, 0]]; |
5ad36be5 | 905 | $query4 = new CRM_Contact_BAO_Query( |
fb1ee468 | 906 | $params4, ['contact_id'], |
5ad36be5 SL |
907 | NULL, TRUE, FALSE, 1, |
908 | TRUE, | |
909 | TRUE, FALSE | |
910 | ); | |
c26679b7 | 911 | $sql4 = $query4->query(); |
299c1530 | 912 | $this->assertLike($from1, $sql4[1]); |
913 | $this->assertLike($where2, $sql4[2]); | |
5de9b484 JP |
914 | |
915 | // Test Multiple b to a Relationship type . | |
fb1ee468 | 916 | $params5 = [['relation_type_id', 'IN', ['8_b_a', '10_b_a', '14_b_a'], 0, 0]]; |
5de9b484 | 917 | $query5 = new CRM_Contact_BAO_Query( |
fb1ee468 | 918 | $params5, ['contact_id'], |
5de9b484 JP |
919 | NULL, TRUE, FALSE, 1, |
920 | TRUE, | |
921 | TRUE, FALSE | |
922 | ); | |
923 | $sql5 = $query5->query(FALSE); | |
299c1530 | 924 | $this->assertLike($from2, $sql5[1]); |
925 | $this->assertLike($where2, $sql5[2]); | |
5ad36be5 | 926 | } |
8d710ea5 | 927 | |
928 | /** | |
929 | * Test we can narrow a group get by status. | |
fb1ee468 | 930 | * |
931 | * @throws \CRM_Core_Exception | |
8d710ea5 | 932 | */ |
933 | public function testGetByGroupWithStatus() { | |
934 | $groupID = $this->groupCreate(); | |
d7570a7f | 935 | $this->groupContactCreate($groupID, 3); |
8d710ea5 | 936 | $groupContactID = $this->callAPISuccessGetSingle('GroupContact', ['group_id' => $groupID, 'options' => ['limit' => 1]])['id']; |
937 | $this->callAPISuccess('GroupContact', 'create', ['id' => $groupContactID, 'status' => 'Removed']); | |
938 | $queryObj = new CRM_Contact_BAO_Query([['group', '=', $groupID, 0, 0], ['group_contact_status', 'IN', ['Removed' => 1], 0, 0]]); | |
939 | $resultDAO = $queryObj->searchQuery(); | |
940 | $this->assertEquals(1, $resultDAO->N); | |
941 | ||
942 | $queryObj = new CRM_Contact_BAO_Query([['group', '=', $groupID, 0, 0], ['group_contact_status', 'IN', ['Added' => 1], 0, 0]]); | |
943 | $resultDAO = $queryObj->searchQuery(); | |
944 | $this->assertEquals(2, $resultDAO->N); | |
945 | ||
946 | $queryObj = new CRM_Contact_BAO_Query([['group', '=', $groupID, 0, 0]]); | |
947 | $resultDAO = $queryObj->searchQuery(); | |
948 | $this->assertEquals(2, $resultDAO->N); | |
949 | } | |
5ad36be5 | 950 | |
0d38cb6d | 951 | /** |
952 | * Test we can narrow a group get by status. | |
953 | * | |
954 | * @throws \Exception | |
955 | */ | |
956 | public function testGetByGroupWithStatusSmartGroup() { | |
957 | $groupID = $this->smartGroupCreate(); | |
958 | // This means they are actually all hard-added, which is fine for this purpose. | |
959 | $this->groupContactCreate($groupID, 3); | |
960 | $groupContactID = $this->callAPISuccessGetSingle('GroupContact', ['group_id' => $groupID, 'options' => ['limit' => 1]])['id']; | |
961 | $this->callAPISuccess('GroupContact', 'create', ['id' => $groupContactID, 'status' => 'Removed']); | |
962 | ||
963 | $queryObj = new CRM_Contact_BAO_Query([['group', '=', $groupID, 0, 0], ['group_contact_status', 'IN', ['Removed' => 1], 0, 0]]); | |
964 | $resultDAO = $queryObj->searchQuery(); | |
965 | $this->assertEquals(1, $resultDAO->N); | |
dd606225 JP |
966 | |
967 | $queryObj = new CRM_Contact_BAO_Query([['group', 'IS NOT EMPTY', '', 0, 0], ['group_contact_status', 'IN', ['Removed' => 1], 0, 0]]); | |
968 | $resultDAO = $queryObj->searchQuery(); | |
969 | $this->assertEquals(1, $resultDAO->N); | |
0d38cb6d | 970 | } |
971 | ||
c3137c08 | 972 | /** |
973 | * Test the group contact clause does not contain an OR. | |
974 | * | |
975 | * The search should return 3 contacts - 2 households in the smart group of | |
976 | * Contact Type = Household and one Individual hard-added to it. The | |
977 | * Household that meets both criteria should be returned once. | |
0d38cb6d | 978 | * |
979 | * @throws \Exception | |
c3137c08 | 980 | */ |
981 | public function testGroupClause() { | |
982 | $this->householdCreate(); | |
983 | $householdID = $this->householdCreate(); | |
984 | $individualID = $this->individualCreate(); | |
985 | $groupID = $this->smartGroupCreate(); | |
fb1ee468 | 986 | $this->callAPISuccess('GroupContact', 'create', ['group_id' => $groupID, 'contact_id' => $individualID, 'status' => 'Added']); |
987 | $this->callAPISuccess('GroupContact', 'create', ['group_id' => $groupID, 'contact_id' => $householdID, 'status' => 'Added']); | |
c3137c08 | 988 | |
485a3a1f | 989 | // Refresh the cache for test purposes. It would be better to alter to alter the GroupContact add function to add contacts to the cache. |
4e465c12 | 990 | CRM_Contact_BAO_GroupContactCache::invalidateGroupContactCache($groupID); |
3875e6b6 | 991 | |
992 | $sql = CRM_Contact_BAO_Query::getQuery( | |
fb1ee468 | 993 | [['group', 'IN', [$groupID], 0, 0]], |
994 | ['contact_id'] | |
c3137c08 | 995 | ); |
996 | ||
3875e6b6 | 997 | $dao = CRM_Core_DAO::executeQuery($sql); |
c3137c08 | 998 | $this->assertEquals(3, $dao->N); |
3875e6b6 | 999 | $this->assertFalse(strstr($sql, ' OR ')); |
1000 | ||
1001 | $sql = CRM_Contact_BAO_Query::getQuery( | |
fb1ee468 | 1002 | [['group', 'IN', [$groupID], 0, 0]], |
1003 | ['contact_id' => 1, 'group' => 1] | |
3875e6b6 | 1004 | ); |
1005 | ||
1006 | $dao = CRM_Core_DAO::executeQuery($sql); | |
1007 | $this->assertEquals(3, $dao->N); | |
1008 | $this->assertFalse(strstr($sql, ' OR '), 'Query does not include or'); | |
1009 | while ($dao->fetch()) { | |
1010 | $this->assertTrue(($dao->groups == $groupID || $dao->groups == ',' . $groupID), $dao->groups . ' includes ' . $groupID); | |
1011 | } | |
c3137c08 | 1012 | } |
1013 | ||
b1128d0b | 1014 | /** |
3af96592 | 1015 | * CRM-19562 ensure that only ids are used for contact_id searching. |
b1128d0b SL |
1016 | */ |
1017 | public function testContactIDClause() { | |
fb1ee468 | 1018 | $params = [ |
8f36c0f5 | 1019 | ['mark_x_2', '=', 1, 0, 0], |
1020 | ['mark_x_foo@example.com', '=', 1, 0, 0], | |
fb1ee468 | 1021 | ]; |
1022 | $returnProperties = [ | |
8f36c0f5 | 1023 | 'sort_name' => 1, |
1024 | 'email' => 1, | |
1025 | 'do_not_email' => 1, | |
1026 | 'is_deceased' => 1, | |
1027 | 'on_hold' => 1, | |
1028 | 'display_name' => 1, | |
1029 | 'preferred_mail_format' => 1, | |
fb1ee468 | 1030 | ]; |
5cf7a77e | 1031 | $numberOfContacts = 2; |
8f36c0f5 | 1032 | |
b1128d0b | 1033 | try { |
8f36c0f5 | 1034 | CRM_Contact_BAO_Query::apiQuery($params, $returnProperties, NULL, NULL, 0, $numberOfContacts); |
b1128d0b SL |
1035 | } |
1036 | catch (Exception $e) { | |
5cf7a77e | 1037 | $this->assertEquals( |
8f36c0f5 | 1038 | 'One of parameters (value: foo@example.com) is not of the type Positive', |
5cf7a77e | 1039 | $e->getMessage() |
1040 | ); | |
1041 | $this->assertTrue(TRUE); | |
1042 | return; | |
b1128d0b | 1043 | } |
5cf7a77e | 1044 | $this->fail('Test failed for some reason which is not good'); |
b1128d0b SL |
1045 | } |
1046 | ||
7f594311 | 1047 | /** |
1048 | * Test the sorting on the contact ID query works. | |
1049 | * | |
1050 | * Checking for lack of fatal. | |
1051 | * | |
1052 | * @param string $sortOrder | |
1053 | * Param reflecting how sort is passed in. | |
1054 | * - 1_d is column 1 descending. | |
1055 | * | |
1056 | * @dataProvider getSortOptions | |
1057 | */ | |
1058 | public function testContactIDQuery($sortOrder) { | |
1059 | $selector = new CRM_Contact_Selector(NULL, ['radio_ts' => 'ts_all'], NULL, ['sort_name' => 1]); | |
1060 | $selector->contactIDQuery([], $sortOrder); | |
1061 | } | |
1062 | ||
708ce91f | 1063 | /** |
1064 | * Test the sorting on the contact ID query works with a profile search. | |
1065 | * | |
1066 | * Checking for lack of fatal. | |
8f36c0f5 | 1067 | * |
1068 | * @throws \CRM_Core_Exception | |
708ce91f | 1069 | */ |
1070 | public function testContactIDQueryProfileSearchResults() { | |
1071 | $profile = $this->callAPISuccess('UFGroup', 'create', ['group_type' => 'Contact', 'name' => 'search', 'title' => 'search']); | |
1072 | $this->callAPISuccess('UFField', 'create', [ | |
1073 | 'uf_group_id' => $profile['id'], | |
1074 | 'field_name' => 'postal_code', | |
1075 | 'field_type' => 'Contact', | |
1076 | 'in_selector' => TRUE, | |
1077 | 'is_searchable' => TRUE, | |
1078 | 'label' => 'postal code', | |
1079 | 'visibility' => 'Public Pages and Listings', | |
1080 | ]); | |
1081 | $selector = new CRM_Contact_Selector(NULL, ['radio_ts' => 'ts_all', 'uf_group_id' => $profile['id']], NULL, ['sort_name' => 1]); | |
1082 | $selector->contactIDQuery([], '2_d'); | |
1083 | } | |
1084 | ||
1085 | /** | |
1086 | * Get search options to reflect how a UI search would look. | |
1087 | * | |
1088 | * @return array | |
1089 | */ | |
7f594311 | 1090 | public function getSortOptions() { |
1091 | return [ | |
1092 | ['1_d'], | |
1093 | ['2_d'], | |
1094 | ['3_d'], | |
1095 | ['4_d'], | |
1096 | ['5_d'], | |
1097 | ['6_d'], | |
1098 | ]; | |
1099 | } | |
dbaa9d7d | 1100 | |
1101 | /** | |
1102 | * Test the summary query does not add an acl clause when acls not enabled.. | |
8f36c0f5 | 1103 | * |
1104 | * @throws \CRM_Core_Exception | |
dbaa9d7d | 1105 | */ |
5384a978 | 1106 | public function testGetSummaryQueryWithFinancialACLDisabled() { |
faba82fc | 1107 | $this->createContributionsForSummaryQueryTests(); |
1108 | ||
1109 | // Test the function directly | |
dbaa9d7d | 1110 | $where = $from = NULL; |
1111 | $queryObject = new CRM_Contact_BAO_Query(); | |
faba82fc | 1112 | $queryObject->appendFinancialTypeWhereAndFromToQueryStrings($where, |
dbaa9d7d | 1113 | $from); |
faba82fc | 1114 | $this->assertEquals(NULL, $where); |
1115 | $this->assertEquals(NULL, $from); | |
1116 | ||
1117 | // Test the function in action | |
1118 | $queryObject = new CRM_Contact_BAO_Query([['contribution_source', '=', 'SSF', '', '']]); | |
1119 | $summary = $queryObject->summaryContribution(); | |
1120 | $this->assertEquals([ | |
1121 | 'total' => [ | |
1122 | 'avg' => '$ 233.33', | |
1123 | 'amount' => '$ 1,400.00', | |
1124 | 'count' => 6, | |
39b959db | 1125 | ], |
faba82fc | 1126 | 'cancel' => [ |
1127 | 'count' => 2, | |
1128 | 'amount' => '$ 100.00', | |
1129 | 'avg' => '$ 50.00', | |
1130 | ], | |
1131 | ], $summary); | |
5384a978 VR |
1132 | } |
1133 | ||
dbaa9d7d | 1134 | /** |
1135 | * Test the summary query accurately adds financial acl filters. | |
8f36c0f5 | 1136 | * |
1137 | * @throws \CRM_Core_Exception | |
dbaa9d7d | 1138 | */ |
5384a978 | 1139 | public function testGetSummaryQueryWithFinancialACLEnabled() { |
dbaa9d7d | 1140 | $where = $from = NULL; |
faba82fc | 1141 | $this->createContributionsForSummaryQueryTests(); |
dbaa9d7d | 1142 | $this->enableFinancialACLs(); |
1143 | $this->createLoggedInUserWithFinancialACL(); | |
faba82fc | 1144 | |
1145 | // Test the function directly | |
dbaa9d7d | 1146 | $queryObject = new CRM_Contact_BAO_Query(); |
faba82fc | 1147 | $queryObject->appendFinancialTypeWhereAndFromToQueryStrings($where, |
dbaa9d7d | 1148 | $from); |
1149 | $donationTypeID = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'financial_type_id', 'Donation'); | |
5384a978 VR |
1150 | $this->assertEquals( |
1151 | " LEFT JOIN civicrm_line_item li | |
1152 | ON civicrm_contribution.id = li.contribution_id AND | |
dbaa9d7d | 1153 | li.entity_table = 'civicrm_contribution' AND li.financial_type_id NOT IN ({$donationTypeID}) ", $from); |
faba82fc | 1154 | |
1155 | // Test the function in action | |
1156 | $queryObject = new CRM_Contact_BAO_Query([['contribution_source', '=', 'SSF', '', '']]); | |
1157 | $summary = $queryObject->summaryContribution(); | |
1158 | $this->assertEquals([ | |
1159 | 'total' => [ | |
1160 | 'avg' => '$ 200.00', | |
1161 | 'amount' => '$ 400.00', | |
1162 | 'count' => 2, | |
faba82fc | 1163 | ], |
1164 | 'cancel' => [ | |
1165 | 'count' => 1, | |
1166 | 'amount' => '$ 50.00', | |
1167 | 'avg' => '$ 50.00', | |
1168 | ], | |
1169 | ], $summary); | |
dbaa9d7d | 1170 | $this->disableFinancialACLs(); |
5384a978 VR |
1171 | } |
1172 | ||
6245de60 JG |
1173 | /** |
1174 | * Test relative date filters to ensure they generate correct SQL. | |
1175 | * | |
1176 | * @dataProvider relativeDateFilters | |
c26679b7 | 1177 | * |
1178 | * @param string $filter | |
1179 | * @param string $expectedWhere | |
1180 | * | |
1181 | * @throws \CRM_Core_Exception | |
6245de60 JG |
1182 | */ |
1183 | public function testRelativeDateFilters($filter, $expectedWhere) { | |
1184 | $params = [['created_date_relative', '=', $filter, 0, 0]]; | |
1185 | ||
1186 | $dates = CRM_Utils_Date::getFromTo($filter, NULL, NULL); | |
1187 | $expectedWhere = str_replace(['date0', 'date1'], [$dates[0], $dates[1]], $expectedWhere); | |
1188 | ||
1189 | $query = new CRM_Contact_BAO_Query( | |
1190 | $params, [], | |
1191 | NULL, TRUE, FALSE, 1, | |
1192 | TRUE, | |
1193 | TRUE, FALSE | |
1194 | ); | |
1195 | ||
1196 | list($select, $from, $where, $having) = $query->query(); | |
1197 | $this->assertEquals($expectedWhere, $where); | |
1198 | } | |
1199 | ||
c26679b7 | 1200 | /** |
1201 | * Data provider to relative date filter configurations. | |
1202 | * | |
1203 | * @return array | |
1204 | */ | |
6245de60 JG |
1205 | public function relativeDateFilters() { |
1206 | $dataProvider[] = ['this.year', "WHERE ( contact_a.created_date BETWEEN 'date0' AND 'date1' ) AND (contact_a.is_deleted = 0)"]; | |
1207 | $dataProvider[] = ['greater.day', "WHERE ( contact_a.created_date >= 'date0' ) AND (contact_a.is_deleted = 0)"]; | |
1208 | $dataProvider[] = ['earlier.week', "WHERE ( contact_a.created_date <= 'date1' ) AND (contact_a.is_deleted = 0)"]; | |
1209 | return $dataProvider; | |
1210 | } | |
1211 | ||
faba82fc | 1212 | /** |
1213 | * Create contributions to test summary calculations. | |
1214 | * | |
1215 | * financial type | cancel_date |total_amount| source | line_item_financial_types |number_line_items| line_amounts | |
1216 | * Donation |NULL | 100.00 |SSF | Donation | 1 | 100.00 | |
1217 | * Member Dues |NULL | 100.00 |SSF | Member Dues | 1 | 100.00 | |
1218 | * Donation |NULL | 300.00 |SSF | Event Fee,Event Fee | 2 | 200.00,100.00 | |
1219 | * Donation |NULL | 300.00 |SSF | Event Fee,Donation | 2 | 200.00,100.00 | |
1220 | * Donation |NULL | 300.00 |SSF | Donation,Donation | 2 | 200.00,100.00 | |
1221 | * Donation |2019-02-13 00:00:00 | 50.00 |SSF | Donation | 1 | 50.00 | |
1222 | * Member Dues |2019-02-13 00:00:00 | 50.00 |SSF | Member Dues | 1 | 50.00 | |
80b5c9f1 | 1223 | * |
1224 | * @throws \CRM_Core_Exception | |
faba82fc | 1225 | */ |
1226 | protected function createContributionsForSummaryQueryTests() { | |
1227 | $contactID = $this->individualCreate(); | |
1228 | $this->contributionCreate(['contact_id' => $contactID]); | |
1229 | $this->contributionCreate([ | |
1230 | 'contact_id' => $contactID, | |
1231 | 'total_amount' => 100, | |
1232 | 'financial_type_id' => 'Member Dues', | |
1233 | ]); | |
1234 | $eventFeeType = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'financial_type_id', 'Event Fee'); | |
1235 | $this->createContributionWithTwoLineItemsAgainstPriceSet(['contact_id' => $contactID, 'source' => 'SSF']); | |
1236 | $this->createContributionWithTwoLineItemsAgainstPriceSet(['contact_id' => $contactID, 'source' => 'SSF'], [ | |
1237 | CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'financial_type_id', 'Donation'), | |
1238 | $eventFeeType, | |
1239 | ]); | |
1240 | $this->createContributionWithTwoLineItemsAgainstPriceSet(['contact_id' => $contactID, 'source' => 'SSF'], [ | |
1241 | CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'financial_type_id', 'Donation'), | |
1242 | CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'financial_type_id', 'Donation'), | |
1243 | ]); | |
1244 | $this->createContributionWithTwoLineItemsAgainstPriceSet(['contact_id' => $contactID, 'source' => 'SSF', 'financial_type_id' => $eventFeeType], [ | |
1245 | CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'financial_type_id', 'Donation'), | |
1246 | CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'financial_type_id', 'Donation'), | |
1247 | ]); | |
1248 | $this->contributionCreate([ | |
1249 | 'contact_id' => $contactID, | |
1250 | 'total_amount' => 50, | |
1251 | 'contribution_status_id' => 'Cancelled', | |
1252 | 'cancel_date' => 'yesterday', | |
1253 | ]); | |
1254 | $this->contributionCreate([ | |
1255 | 'contact_id' => $contactID, | |
1256 | 'total_amount' => 50, | |
1257 | 'contribution_status_id' => 'Cancelled', | |
1258 | 'cancel_date' => 'yesterday', | |
1259 | 'financial_type_id' => 'Member Dues', | |
1260 | ]); | |
1261 | } | |
1262 | ||
3fc41a5d | 1263 | /** |
1264 | * Test the options are handled for the qill. | |
1265 | */ | |
1266 | public function testQillOptions() { | |
1267 | $qill = CRM_Contact_BAO_Query::buildQillForFieldValue('CRM_Activity_BAO_Activity', 'activity_type_id', 2, '='); | |
1268 | $this->assertEquals(['=', 'Phone Call'], $qill); | |
1269 | ||
1270 | $qill = CRM_Contact_BAO_Query::buildQillForFieldValue('CRM_Activity_BAO_Activity', 'priority_id', 2, '='); | |
1271 | $this->assertEquals(['=', 'Normal'], $qill); | |
1272 | } | |
1273 | ||
9724097e | 1274 | /** |
1275 | * Test tests that a value on 'any entity' with the right metadata will be handled. | |
1276 | * | |
1277 | * @throws \CRM_Core_Exception | |
1278 | */ | |
1279 | public function testGenericWhereHandling() { | |
1280 | $query = new CRM_Contact_BAO_Query([['suffix_id', '=', 2, 0]]); | |
c26679b7 | 1281 | $this->assertEquals('contact_a.suffix_id = 2', $query->_where[0][0]); |
9724097e | 1282 | $this->assertEquals('Individual Suffix = Sr.', $query->_qill[0][0]); |
1283 | $this->assertNotTrue(isset($query->_tables['civicrm_activity'])); | |
1284 | ||
1285 | $query = new CRM_Contact_BAO_Query([['prefix_id', '=', 2, 0]]); | |
1286 | $this->assertEquals('contact_a.prefix_id = 2', $query->_where[0][0]); | |
1287 | $this->assertEquals('Individual Prefix = Ms.', $query->_qill[0][0]); | |
1288 | $this->assertNotTrue(isset($query->_tables['civicrm_activity'])); | |
1289 | ||
1290 | $query = new CRM_Contact_BAO_Query([['gender_id', '=', 2, 0]]); | |
1291 | $this->assertEquals('contact_a.gender_id = 2', $query->_where[0][0]); | |
1292 | $this->assertEquals('Gender = Male', $query->_qill[0][0]); | |
1293 | $this->assertNotTrue(isset($query->_tables['civicrm_activity'])); | |
1294 | ||
1295 | $query = new CRM_Contact_BAO_Query([['communication_style_id', '=', 2, 0]]); | |
1296 | $this->assertEquals('contact_a.communication_style_id = 2', $query->_where[0][0]); | |
1297 | $this->assertEquals('Communication Style = Familiar', $query->_qill[0][0]); | |
1298 | ||
1299 | $query = new CRM_Contact_BAO_Query([['communication_style_id', '=', 2, 0]]); | |
1300 | $this->assertEquals('contact_a.communication_style_id = 2', $query->_where[0][0]); | |
1301 | $this->assertEquals('Communication Style = Familiar', $query->_qill[0][0]); | |
1302 | ||
1303 | $query = new CRM_Contact_BAO_Query([['contact_type', '=', 'Household', 0]]); | |
1304 | $this->assertEquals("contact_a.contact_type = 'Household'", $query->_where[0][0]); | |
1305 | $this->assertEquals('Contact Type = Household', $query->_qill[0][0]); | |
1306 | ||
1307 | $query = new CRM_Contact_BAO_Query([['on_hold', '=', 0, 0]]); | |
1308 | $this->assertEquals('civicrm_email.on_hold = 0', $query->_where[0][0]); | |
1309 | $this->assertEquals('On Hold = 0', $query->_qill[0][0]); | |
1310 | ||
1311 | $query = new CRM_Contact_BAO_Query([['on_hold', '=', 1, 0]]); | |
1312 | $this->assertEquals('civicrm_email.on_hold = 1', $query->_where[0][0]); | |
1313 | $this->assertEquals('On Hold = 1', $query->_qill[0][0]); | |
1314 | ||
1315 | $query = new CRM_Contact_BAO_Query([['world_region', '=', 3, 0]]); | |
1316 | $this->assertEquals('civicrm_worldregion.id = 3', $query->_where[0][0]); | |
1317 | $this->assertEquals('World Region = Middle East and North Africa', $query->_qill[0][0]); | |
1318 | } | |
1319 | ||
6a488035 | 1320 | } |