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