Merge pull request #16469 from civicrm/5.22
[civicrm-core.git] / tests / phpunit / api / v3 / JobTestCustomDataTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
10 */
11
12 /**
13 * File for the CiviCRM APIv3 job functions
14 *
15 * @package CiviCRM_APIv3
16 * @subpackage API_Job
17 *
18 * @copyright CiviCRM LLC https://civicrm.org/licensing
19 * @version $Id: Job.php 30879 2010-11-22 15:45:55Z shot $
20 *
21 */
22
23 /**
24 * Tests for job api where custom data is involved.
25 *
26 * Set up for custom data won't work with useTransaction so these are not
27 * compatible with the other job test class.
28 *
29 * @group headless
30 */
31 class api_v3_JobTestCustomDataTest extends CiviUnitTestCase {
32 protected $_apiversion = 3;
33
34 public $_entity = 'Job';
35
36 /**
37 * Custom group ID.
38 *
39 * @var int
40 */
41 public $customFieldID = NULL;
42
43 /**
44 * ID of a custom field of integer type.
45 *
46 * @var int
47 */
48 public $customIntFieldID = NULL;
49
50 /**
51 * ID of a custom field of integer type.
52 *
53 * @var int
54 */
55 public $customBoolFieldID = NULL;
56
57 /**
58 * ID of a custom field of integer type.
59 *
60 * @var int
61 */
62 public $customStringCheckboxID = NULL;
63
64 /**
65 * Custom Field ID.
66 *
67 * @var int
68 */
69 public $customGroupID = NULL;
70
71 public function setUp() {
72 parent::setUp();
73 $customGroup = $this->customGroupCreate();
74 $this->customGroupID = $customGroup['id'];
75 $customField = $this->customFieldCreate([
76 'custom_group_id' => $this->customGroupID,
77 'data_type' => 'Date',
78 'html_type' => 'Select Date',
79 'default_value' => '',
80 ]);
81 $this->customFieldID = $customField['id'];
82 $customField = $this->customFieldCreate([
83 'custom_group_id' => $this->customGroupID,
84 'data_type' => 'Integer',
85 'html_type' => 'Text',
86 'default_value' => '',
87 'label' => 'Int Field',
88 ]);
89 $this->customIntFieldID = $customField['id'];
90 $customField = $this->customFieldCreate([
91 'custom_group_id' => $this->customGroupID,
92 'data_type' => 'Boolean',
93 'html_type' => 'Radio',
94 'default_value' => '',
95 'label' => 'Radio Field',
96 ]);
97 $this->customBoolFieldID = $customField['id'];
98 $customField = $this->customFieldCreate([
99 'custom_group_id' => $this->customGroupID,
100 'data_type' => 'String',
101 'html_type' => 'CheckBox',
102 'default_value' => NULL,
103 'label' => 'checkbox Field',
104 'option_values' => ['black' => 'black', 'white' => 'white'],
105 ]);
106 $this->customStringCheckboxID = $customField['id'];
107 }
108
109 /**
110 * Cleanup after tests.
111 *
112 * @throws \CRM_Core_Exception
113 */
114 public function tearDown() {
115 $this->quickCleanup(['civicrm_contact'], TRUE);
116 parent::tearDown();
117 }
118
119 /**
120 * Test the batch merge does not bork on custom date fields.
121 *
122 * @dataProvider getCheckboxData
123 *
124 * Test CRM-19074 checkbox field handling.
125 *
126 * Given a custom field with 2 checkboxes (black & white) possible values are:
127 * 1) SEPARATOR + black + SEPARATOR
128 * 2) SEPARATOR + white + SEPARATOR
129 * 3) SEPARATOR + black + SEPARATOR + white + SEPARATOR
130 * 3) '' (ie empty string means both set to 0)
131 * 4) NULL (ie not set)
132 * - in safe mode NULL is not a conflict with any option but the other
133 * combos are a conflict.
134 *
135 * @param array $dataSet
136 *
137 * @throws \CRM_Core_Exception
138 */
139 public function testBatchMergeCheckboxCustomFieldHandling($dataSet) {
140 $customFieldLabel = 'custom_' . $this->customStringCheckboxID;
141 $contact1Params = is_array($dataSet['contacts'][0]) ? [$customFieldLabel => $dataSet['contacts'][0]] : [];
142 $contact2Params = is_array($dataSet['contacts'][1]) ? [$customFieldLabel => $dataSet['contacts'][1]] : [];
143 $contactID = $this->individualCreate($contact1Params);
144 $this->individualCreate($contact2Params);
145 $result = $this->callAPISuccess('Job', 'process_batch_merge', ['mode' => $dataSet['mode']]);
146 $this->assertCount($dataSet['merged'], $result['values']['merged']);
147 $this->assertCount($dataSet['skipped'], $result['values']['skipped']);
148 $contact = $this->callAPISuccess('Contact', 'getsingle', ['id' => $contactID, 'return' => $customFieldLabel]);
149 $this->assertEquals($dataSet['expected'], $contact[$customFieldLabel]);
150 }
151
152 /**
153 * Get the various data combinations for a checkbox field.
154 *
155 * @return array
156 */
157 public function getCheckboxData() {
158 $data = [
159 [
160 'null_merges_with_set' => [
161 'mode' => 'safe',
162 'contacts' => [
163 NULL,
164 ['black'],
165 ],
166 'skipped' => 0,
167 'merged' => 1,
168 'expected' => ['black'],
169 ],
170 ],
171 [
172 'null_merges_with_set_reverse' => [
173 'mode' => 'safe',
174 'contacts' => [
175 ['black'],
176 NULL,
177 ],
178 'skipped' => 0,
179 'merged' => 1,
180 'expected' => ['black'],
181
182 ],
183 ],
184 [
185 'empty_conflicts_with_set' => [
186 'mode' => 'safe',
187 'contacts' => [
188 ['white'],
189 ['black'],
190 ],
191 'skipped' => 1,
192 'merged' => 0,
193 'expected' => ['white'],
194 ],
195 ],
196 [
197 'empty_conflicts_with_set' => [
198 'mode' => 'aggressive',
199 'contacts' => [
200 ['white'],
201 ['black'],
202 ],
203 'skipped' => 0,
204 'merged' => 1,
205 'expected' => ['white'],
206 ],
207 ],
208 ];
209 return $data;
210 }
211
212 /**
213 * Test the batch merge does not bork on custom date fields.
214 *
215 * Test CRM-18674 date custom field handling.
216 */
217 public function testBatchMergeDateCustomFieldHandling() {
218 $customFieldLabel = 'custom_' . $this->customFieldID;
219 $contactID = $this->individualCreate();
220 $this->individualCreate([$customFieldLabel => '2012-12-03']);
221 $result = $this->callAPISuccess('Job', 'process_batch_merge', []);
222 $this->assertEquals(1, count($result['values']['merged']));
223 $contact = $this->callAPISuccess('Contact', 'getsingle', ['id' => $contactID, 'return' => $customFieldLabel]);
224 $this->assertEquals('2012-12-03 00:00:00', $contact[$customFieldLabel]);
225 }
226
227 /**
228 * Test the batch merge does not bork on custom date fields.
229 *
230 * Test CRM-18674 date custom field handling.
231 */
232 public function testBatchMergeDateCustomFieldHandlingIsView() {
233 $this->customFieldCreate([
234 'label' => 'OnlyView',
235 'custom_group_id' => $this->customGroupID,
236 'is_view' => 1,
237 ]);
238 $customFieldLabel = 'custom_' . $this->customFieldID;
239 $contactID = $this->individualCreate();
240 $this->individualCreate([$customFieldLabel => '2012-11-03']);
241 $result = $this->callAPISuccess('Job', 'process_batch_merge', []);
242 $this->assertEquals(1, count($result['values']['merged']));
243 $contact = $this->callAPISuccess('Contact', 'getsingle', ['id' => $contactID, 'return' => $customFieldLabel]);
244 $this->assertEquals('2012-11-03 00:00:00', $contact[$customFieldLabel]);
245 }
246
247 /**
248 * Check we get a conflict on the custom field.
249 */
250 public function testBatchMergeDateCustomFieldConflict() {
251 $customFieldLabel = 'custom_' . $this->customFieldID;
252 $contactID = $this->individualCreate([$customFieldLabel => '2012-11-03']);
253 $this->individualCreate([$customFieldLabel => '2013-11-03']);
254 $result = $this->callAPISuccess('Job', 'process_batch_merge', []);
255 $this->assertEquals(0, count($result['values']['merged']));
256 $this->assertEquals(1, count($result['values']['skipped']));
257 $contact = $this->callAPISuccess('Contact', 'getsingle', ['id' => $contactID, 'return' => $customFieldLabel]);
258 $this->assertEquals('2012-11-03 00:00:00', $contact[$customFieldLabel]);
259 }
260
261 /**
262 * Check we get a conflict on the custom field.
263 */
264 public function testBatchMergeDateCustomFieldNoConflict() {
265 $customFieldLabel = 'custom_' . $this->customFieldID;
266 $contactID = $this->individualCreate([$customFieldLabel => '2012-11-03']);
267 $this->individualCreate([$customFieldLabel => '2012-11-03']);
268 $result = $this->callAPISuccess('Job', 'process_batch_merge', []);
269 $this->assertEquals(1, count($result['values']['merged']));
270 $this->assertEquals(0, count($result['values']['skipped']));
271 $contact = $this->callAPISuccess('Contact', 'getsingle', ['id' => $contactID, 'return' => $customFieldLabel]);
272 $this->assertEquals('2012-11-03 00:00:00', $contact[$customFieldLabel]);
273 }
274
275 /**
276 * Check we get a no conflict on the custom field & integer merges.
277 */
278 public function testBatchMergeIntCustomFieldNoConflict() {
279 $customFieldLabel = 'custom_' . $this->customIntFieldID;
280 $contactID = $this->individualCreate([]);
281 $this->individualCreate([$customFieldLabel => 20]);
282 $result = $this->callAPISuccess('Job', 'process_batch_merge', []);
283 $this->assertEquals(1, count($result['values']['merged']));
284 $this->assertEquals(0, count($result['values']['skipped']));
285 $contact = $this->callAPISuccess('Contact', 'getsingle', ['id' => $contactID, 'return' => $customFieldLabel]);
286 $this->assertEquals(20, $contact[$customFieldLabel]);
287 }
288
289 /**
290 * Check we get a conflict on the integer custom field.
291 */
292 public function testBatchMergeIntCustomFieldConflict() {
293 $customFieldLabel = 'custom_' . $this->customIntFieldID;
294 $contactID = $this->individualCreate([$customFieldLabel => 20]);
295 $this->individualCreate([$customFieldLabel => 1]);
296 $result = $this->callAPISuccess('Job', 'process_batch_merge', []);
297 $this->assertEquals(0, count($result['values']['merged']));
298 $this->assertEquals(1, count($result['values']['skipped']));
299 $contact = $this->callAPISuccess('Contact', 'getsingle', ['id' => $contactID, 'return' => $customFieldLabel]);
300 $this->assertEquals(20, $contact[$customFieldLabel]);
301 }
302
303 /**
304 * Check we get a conflict on the integer custom field when the conflicted field is 0.
305 */
306 public function testBatchMergeIntCustomFieldConflictZero() {
307 $customFieldLabel = 'custom_' . $this->customIntFieldID;
308 $contactID = $this->individualCreate([$customFieldLabel => 0]);
309 $this->individualCreate([$customFieldLabel => 20]);
310 $result = $this->callAPISuccess('Job', 'process_batch_merge', []);
311 $this->assertEquals(0, count($result['values']['merged']));
312 $this->assertEquals(1, count($result['values']['skipped']));
313 $contact = $this->callAPISuccess('Contact', 'getsingle', ['id' => $contactID, 'return' => $customFieldLabel]);
314 $this->assertEquals(0, $contact[$customFieldLabel]);
315 }
316
317 /**
318 * Using the api with check perms set to off, make sure custom data is merged.
319 *
320 * Test CRM-18674 date custom field handling.
321 */
322 public function testBatchMergeDateCustomFieldConflictAndNoCheckPerms() {
323 CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM', 'edit my contact'];
324 CRM_Core_DAO::executeQuery("DELETE FROM civicrm_cache");
325 CRM_Utils_System::flushCache();
326 $customFieldLabel = 'custom_' . $this->customFieldID;
327 $contactID = $this->individualCreate([$customFieldLabel => '2012-11-03']);
328 $this->individualCreate([$customFieldLabel => '2013-11-03']);
329 $result = $this->callAPISuccess('Job', 'process_batch_merge', ['check_permissions' => 0]);
330 $this->assertEquals(0, count($result['values']['merged']));
331 $this->assertEquals(1, count($result['values']['skipped']));
332 $contact = $this->callAPISuccess('Contact', 'getsingle', ['id' => $contactID, 'return' => $customFieldLabel]);
333 $this->assertEquals('2012-11-03 00:00:00', $contact[$customFieldLabel]);
334 }
335
336 /**
337 * Using the api with check perms set to off, make sure custom data is merged.
338 *
339 * Test CRM-18674 date custom field handling.
340 */
341 public function testBatchMergeDateCustomFieldNoConflictAndNoCheckPerms() {
342 CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM', 'edit my contact'];
343 CRM_Core_DAO::executeQuery("DELETE FROM civicrm_cache");
344 CRM_Utils_System::flushCache();
345 $customFieldLabel = 'custom_' . $this->customFieldID;
346 $contactID = $this->individualCreate();
347 $this->individualCreate([$customFieldLabel => '2013-11-03']);
348 $result = $this->callAPISuccess('Job', 'process_batch_merge', ['check_permissions' => 0]);
349 $this->assertEquals(1, count($result['values']['merged']));
350 $this->assertEquals(0, count($result['values']['skipped']));
351 $contact = $this->callAPISuccess('Contact', 'getsingle', ['id' => $contactID, 'return' => $customFieldLabel]);
352 $this->assertEquals('2013-11-03 00:00:00', $contact[$customFieldLabel]);
353 }
354
355 /**
356 * Using the api with check perms set to off, make sure custom data is merged.
357 *
358 * Test CRM-19113 custom data lost when permissions in play.
359 */
360 public function testBatchMergeIntCustomFieldNoConflictAndNoCheckPerms() {
361 CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM', 'edit my contact'];
362 CRM_Core_DAO::executeQuery("DELETE FROM civicrm_cache");
363 CRM_Utils_System::flushCache();
364 $customFieldLabel = 'custom_' . $this->customIntFieldID;
365 $contactID = $this->individualCreate(['custom_' . $this->customBoolFieldID => 1]);
366 $this->individualCreate([$customFieldLabel => 1, 'custom_' . $this->customBoolFieldID => 1]);
367 $result = $this->callAPISuccess('Job', 'process_batch_merge', ['check_permissions' => 0]);
368 $this->assertEquals(1, count($result['values']['merged']));
369 $this->assertEquals(0, count($result['values']['skipped']));
370 $contact = $this->callAPISuccess('Contact', 'getsingle', [
371 'id' => $contactID,
372 'return' => [$customFieldLabel, 'custom_' . $this->customBoolFieldID],
373 ]);
374 $this->assertEquals(1, $contact[$customFieldLabel]);
375 $this->assertEquals(1, $contact['custom_' . $this->customBoolFieldID]);
376 }
377
378 /**
379 * Check we get a conflict on the customs field when the data conflicts for booleans.
380 */
381 public function testBatchMergeCustomFieldConflicts() {
382 $this->individualCreate(['custom_' . $this->customBoolFieldID => 0]);
383 $this->individualCreate(['custom_' . $this->customBoolFieldID => 1]);
384 $result = $this->callAPISuccess('Job', 'process_batch_merge', []);
385 $this->assertEquals(0, count($result['values']['merged']));
386 $this->assertEquals(1, count($result['values']['skipped']));
387 }
388
389 /**
390 * Check we get a conflict on the customs field when the data conflicts for booleans (reverse).
391 */
392 public function testBatchMergeCustomFieldConflictsReverse() {
393 $this->individualCreate(['custom_' . $this->customBoolFieldID => 1]);
394 $this->individualCreate(['custom_' . $this->customBoolFieldID => 0]);
395 $result = $this->callAPISuccess('Job', 'process_batch_merge', []);
396 $this->assertEquals(0, count($result['values']['merged']));
397 $this->assertEquals(1, count($result['values']['skipped']));
398 }
399
400 /**
401 * Check we get a conflict on the customs field when the data conflicts for booleans (reverse).
402 */
403 public function testBatchMergeCustomFieldConflictsOneBlank() {
404 $this->individualCreate(['custom_' . $this->customBoolFieldID => 1]);
405 $this->individualCreate();
406 $result = $this->callAPISuccess('Job', 'process_batch_merge', []);
407 $this->assertEquals(1, count($result['values']['merged']));
408 $this->assertEquals(0, count($result['values']['skipped']));
409 }
410
411 /**
412 * Check we get a conflict on the customs field when the data conflicts for booleans (reverse).
413 */
414 public function testBatchMergeCustomFieldConflictsOneBlankReverse() {
415 $this->individualCreate();
416 $this->individualCreate(['custom_' . $this->customBoolFieldID => 1]);
417 $result = $this->callAPISuccess('Job', 'process_batch_merge', []);
418 $this->assertEquals(1, count($result['values']['merged']));
419 $this->assertEquals(0, count($result['values']['skipped']));
420 }
421
422 }