Merge pull request #16004 from civicrm/5.20
[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 public function tearDown() {
113 $this->quickCleanup(['civicrm_contact'], TRUE);
114 parent::tearDown();
115 }
116
117 /**
118 * Test the batch merge does not bork on custom date fields.
119 *
120 * @dataProvider getCheckboxData
121 *
122 * Test CRM-19074 checkbox field handling.
123 *
124 * Given a custom field with 2 checkboxes (black & white) possible values are:
125 * 1) SEPARATOR + black + SEPARATOR
126 * 2) SEPARATOR + white + SEPARATOR
127 * 3) SEPARATOR + black + SEPARATOR + white + SEPARATOR
128 * 3) '' (ie empty string means both set to 0)
129 * 4) NULL (ie not set)
130 * - in safe mode NULL is not a conflict with any option but the other
131 * combos are a conflict.
132 */
133 public function testBatchMergeCheckboxCustomFieldHandling($dataSet) {
134 $customFieldLabel = 'custom_' . $this->customStringCheckboxID;
135 $contact1Params = is_array($dataSet['contacts'][0]) ? [$customFieldLabel => $dataSet['contacts'][0]] : [];
136 $contact2Params = is_array($dataSet['contacts'][1]) ? [$customFieldLabel => $dataSet['contacts'][1]] : [];
137 $contactID = $this->individualCreate($contact1Params);
138 $this->individualCreate($contact2Params);
139 $result = $this->callAPISuccess('Job', 'process_batch_merge', ['mode' => $dataSet['mode']]);
140 $this->assertEquals($dataSet['merged'], count($result['values']['merged']));
141 $this->assertEquals($dataSet['skipped'], count($result['values']['skipped']));
142 $contact = $this->callAPISuccess('Contact', 'getsingle', ['id' => $contactID, 'return' => $customFieldLabel]);
143 $this->assertEquals($dataSet['expected'], $contact[$customFieldLabel]);
144 }
145
146 /**
147 * Get the various data combinations for a checkbox field.
148 *
149 * @return array
150 */
151 public function getCheckboxData() {
152 $data = [
153 [
154 'null_merges_with_set' => [
155 'mode' => 'safe',
156 'contacts' => [
157 NULL,
158 ['black'],
159 ],
160 'skipped' => 0,
161 'merged' => 1,
162 'expected' => ['black'],
163 ],
164 ],
165 [
166 'null_merges_with_set_reverse' => [
167 'mode' => 'safe',
168 'contacts' => [
169 ['black'],
170 NULL,
171 ],
172 'skipped' => 0,
173 'merged' => 1,
174 'expected' => ['black'],
175
176 ],
177 ],
178 [
179 'empty_conflicts_with_set' => [
180 'mode' => 'safe',
181 'contacts' => [
182 ['white'],
183 ['black'],
184 ],
185 'skipped' => 1,
186 'merged' => 0,
187 'expected' => ['white'],
188 ],
189 ],
190 [
191 'empty_conflicts_with_set' => [
192 'mode' => 'aggressive',
193 'contacts' => [
194 ['white'],
195 ['black'],
196 ],
197 'skipped' => 0,
198 'merged' => 1,
199 'expected' => ['white'],
200 ],
201 ],
202 ];
203 return $data;
204 }
205
206 /**
207 * Test the batch merge does not bork on custom date fields.
208 *
209 * Test CRM-18674 date custom field handling.
210 */
211 public function testBatchMergeDateCustomFieldHandling() {
212 $customFieldLabel = 'custom_' . $this->customFieldID;
213 $contactID = $this->individualCreate();
214 $this->individualCreate([$customFieldLabel => '2012-12-03']);
215 $result = $this->callAPISuccess('Job', 'process_batch_merge', []);
216 $this->assertEquals(1, count($result['values']['merged']));
217 $contact = $this->callAPISuccess('Contact', 'getsingle', ['id' => $contactID, 'return' => $customFieldLabel]);
218 $this->assertEquals('2012-12-03 00:00:00', $contact[$customFieldLabel]);
219 }
220
221 /**
222 * Test the batch merge does not bork on custom date fields.
223 *
224 * Test CRM-18674 date custom field handling.
225 */
226 public function testBatchMergeDateCustomFieldHandlingIsView() {
227 $this->customFieldCreate([
228 'label' => 'OnlyView',
229 'custom_group_id' => $this->customGroupID,
230 'is_view' => 1,
231 ]);
232 $customFieldLabel = 'custom_' . $this->customFieldID;
233 $contactID = $this->individualCreate();
234 $this->individualCreate([$customFieldLabel => '2012-11-03']);
235 $result = $this->callAPISuccess('Job', 'process_batch_merge', []);
236 $this->assertEquals(1, count($result['values']['merged']));
237 $contact = $this->callAPISuccess('Contact', 'getsingle', ['id' => $contactID, 'return' => $customFieldLabel]);
238 $this->assertEquals('2012-11-03 00:00:00', $contact[$customFieldLabel]);
239 }
240
241 /**
242 * Check we get a conflict on the custom field.
243 */
244 public function testBatchMergeDateCustomFieldConflict() {
245 $customFieldLabel = 'custom_' . $this->customFieldID;
246 $contactID = $this->individualCreate([$customFieldLabel => '2012-11-03']);
247 $this->individualCreate([$customFieldLabel => '2013-11-03']);
248 $result = $this->callAPISuccess('Job', 'process_batch_merge', []);
249 $this->assertEquals(0, count($result['values']['merged']));
250 $this->assertEquals(1, count($result['values']['skipped']));
251 $contact = $this->callAPISuccess('Contact', 'getsingle', ['id' => $contactID, 'return' => $customFieldLabel]);
252 $this->assertEquals('2012-11-03 00:00:00', $contact[$customFieldLabel]);
253 }
254
255 /**
256 * Check we get a conflict on the custom field.
257 */
258 public function testBatchMergeDateCustomFieldNoConflict() {
259 $customFieldLabel = 'custom_' . $this->customFieldID;
260 $contactID = $this->individualCreate([$customFieldLabel => '2012-11-03']);
261 $this->individualCreate([$customFieldLabel => '2012-11-03']);
262 $result = $this->callAPISuccess('Job', 'process_batch_merge', []);
263 $this->assertEquals(1, count($result['values']['merged']));
264 $this->assertEquals(0, count($result['values']['skipped']));
265 $contact = $this->callAPISuccess('Contact', 'getsingle', ['id' => $contactID, 'return' => $customFieldLabel]);
266 $this->assertEquals('2012-11-03 00:00:00', $contact[$customFieldLabel]);
267 }
268
269 /**
270 * Check we get a no conflict on the custom field & integer merges.
271 */
272 public function testBatchMergeIntCustomFieldNoConflict() {
273 $customFieldLabel = 'custom_' . $this->customIntFieldID;
274 $contactID = $this->individualCreate([]);
275 $this->individualCreate([$customFieldLabel => 20]);
276 $result = $this->callAPISuccess('Job', 'process_batch_merge', []);
277 $this->assertEquals(1, count($result['values']['merged']));
278 $this->assertEquals(0, count($result['values']['skipped']));
279 $contact = $this->callAPISuccess('Contact', 'getsingle', ['id' => $contactID, 'return' => $customFieldLabel]);
280 $this->assertEquals(20, $contact[$customFieldLabel]);
281 }
282
283 /**
284 * Check we get a conflict on the integer custom field.
285 */
286 public function testBatchMergeIntCustomFieldConflict() {
287 $customFieldLabel = 'custom_' . $this->customIntFieldID;
288 $contactID = $this->individualCreate([$customFieldLabel => 20]);
289 $this->individualCreate([$customFieldLabel => 1]);
290 $result = $this->callAPISuccess('Job', 'process_batch_merge', []);
291 $this->assertEquals(0, count($result['values']['merged']));
292 $this->assertEquals(1, count($result['values']['skipped']));
293 $contact = $this->callAPISuccess('Contact', 'getsingle', ['id' => $contactID, 'return' => $customFieldLabel]);
294 $this->assertEquals(20, $contact[$customFieldLabel]);
295 }
296
297 /**
298 * Check we get a conflict on the integer custom field when the conflicted field is 0.
299 */
300 public function testBatchMergeIntCustomFieldConflictZero() {
301 $customFieldLabel = 'custom_' . $this->customIntFieldID;
302 $contactID = $this->individualCreate([$customFieldLabel => 0]);
303 $this->individualCreate([$customFieldLabel => 20]);
304 $result = $this->callAPISuccess('Job', 'process_batch_merge', []);
305 $this->assertEquals(0, count($result['values']['merged']));
306 $this->assertEquals(1, count($result['values']['skipped']));
307 $contact = $this->callAPISuccess('Contact', 'getsingle', ['id' => $contactID, 'return' => $customFieldLabel]);
308 $this->assertEquals(0, $contact[$customFieldLabel]);
309 }
310
311 /**
312 * Using the api with check perms set to off, make sure custom data is merged.
313 *
314 * Test CRM-18674 date custom field handling.
315 */
316 public function testBatchMergeDateCustomFieldConflictAndNoCheckPerms() {
317 CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM', 'edit my contact'];
318 CRM_Core_DAO::executeQuery("DELETE FROM civicrm_cache");
319 CRM_Utils_System::flushCache();
320 $customFieldLabel = 'custom_' . $this->customFieldID;
321 $contactID = $this->individualCreate([$customFieldLabel => '2012-11-03']);
322 $this->individualCreate([$customFieldLabel => '2013-11-03']);
323 $result = $this->callAPISuccess('Job', 'process_batch_merge', ['check_permissions' => 0]);
324 $this->assertEquals(0, count($result['values']['merged']));
325 $this->assertEquals(1, count($result['values']['skipped']));
326 $contact = $this->callAPISuccess('Contact', 'getsingle', ['id' => $contactID, 'return' => $customFieldLabel]);
327 $this->assertEquals('2012-11-03 00:00:00', $contact[$customFieldLabel]);
328 }
329
330 /**
331 * Using the api with check perms set to off, make sure custom data is merged.
332 *
333 * Test CRM-18674 date custom field handling.
334 */
335 public function testBatchMergeDateCustomFieldNoConflictAndNoCheckPerms() {
336 CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM', 'edit my contact'];
337 CRM_Core_DAO::executeQuery("DELETE FROM civicrm_cache");
338 CRM_Utils_System::flushCache();
339 $customFieldLabel = 'custom_' . $this->customFieldID;
340 $contactID = $this->individualCreate();
341 $this->individualCreate([$customFieldLabel => '2013-11-03']);
342 $result = $this->callAPISuccess('Job', 'process_batch_merge', ['check_permissions' => 0]);
343 $this->assertEquals(1, count($result['values']['merged']));
344 $this->assertEquals(0, count($result['values']['skipped']));
345 $contact = $this->callAPISuccess('Contact', 'getsingle', ['id' => $contactID, 'return' => $customFieldLabel]);
346 $this->assertEquals('2013-11-03 00:00:00', $contact[$customFieldLabel]);
347 }
348
349 /**
350 * Using the api with check perms set to off, make sure custom data is merged.
351 *
352 * Test CRM-19113 custom data lost when permissions in play.
353 */
354 public function testBatchMergeIntCustomFieldNoConflictAndNoCheckPerms() {
355 CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM', 'edit my contact'];
356 CRM_Core_DAO::executeQuery("DELETE FROM civicrm_cache");
357 CRM_Utils_System::flushCache();
358 $customFieldLabel = 'custom_' . $this->customIntFieldID;
359 $contactID = $this->individualCreate(['custom_' . $this->customBoolFieldID => 1]);
360 $this->individualCreate([$customFieldLabel => 1, 'custom_' . $this->customBoolFieldID => 1]);
361 $result = $this->callAPISuccess('Job', 'process_batch_merge', ['check_permissions' => 0]);
362 $this->assertEquals(1, count($result['values']['merged']));
363 $this->assertEquals(0, count($result['values']['skipped']));
364 $contact = $this->callAPISuccess('Contact', 'getsingle', [
365 'id' => $contactID,
366 'return' => [$customFieldLabel, 'custom_' . $this->customBoolFieldID],
367 ]);
368 $this->assertEquals(1, $contact[$customFieldLabel]);
369 $this->assertEquals(1, $contact['custom_' . $this->customBoolFieldID]);
370 }
371
372 /**
373 * Check we get a conflict on the customs field when the data conflicts for booleans.
374 */
375 public function testBatchMergeCustomFieldConflicts() {
376 $this->individualCreate(['custom_' . $this->customBoolFieldID => 0]);
377 $this->individualCreate(['custom_' . $this->customBoolFieldID => 1]);
378 $result = $this->callAPISuccess('Job', 'process_batch_merge', []);
379 $this->assertEquals(0, count($result['values']['merged']));
380 $this->assertEquals(1, count($result['values']['skipped']));
381 }
382
383 /**
384 * Check we get a conflict on the customs field when the data conflicts for booleans (reverse).
385 */
386 public function testBatchMergeCustomFieldConflictsReverse() {
387 $this->individualCreate(['custom_' . $this->customBoolFieldID => 1]);
388 $this->individualCreate(['custom_' . $this->customBoolFieldID => 0]);
389 $result = $this->callAPISuccess('Job', 'process_batch_merge', []);
390 $this->assertEquals(0, count($result['values']['merged']));
391 $this->assertEquals(1, count($result['values']['skipped']));
392 }
393
394 /**
395 * Check we get a conflict on the customs field when the data conflicts for booleans (reverse).
396 */
397 public function testBatchMergeCustomFieldConflictsOneBlank() {
398 $this->individualCreate(['custom_' . $this->customBoolFieldID => 1]);
399 $this->individualCreate();
400 $result = $this->callAPISuccess('Job', 'process_batch_merge', []);
401 $this->assertEquals(1, count($result['values']['merged']));
402 $this->assertEquals(0, count($result['values']['skipped']));
403 }
404
405 /**
406 * Check we get a conflict on the customs field when the data conflicts for booleans (reverse).
407 */
408 public function testBatchMergeCustomFieldConflictsOneBlankReverse() {
409 $this->individualCreate();
410 $this->individualCreate(['custom_' . $this->customBoolFieldID => 1]);
411 $result = $this->callAPISuccess('Job', 'process_batch_merge', []);
412 $this->assertEquals(1, count($result['values']['merged']));
413 $this->assertEquals(0, count($result['values']['skipped']));
414 }
415
416 }