Merge pull request #11772 from michaelmcandrew/CRM-21821-respect-nav-item-weight
[civicrm-core.git] / tests / phpunit / api / v3 / CustomFieldTest.php
CommitLineData
6a488035 1<?php
b6708aeb 2/*
3 +--------------------------------------------------------------------+
2fe49090 4| CiviCRM version 5 |
b6708aeb 5+--------------------------------------------------------------------+
8c9251b3 6| Copyright CiviCRM LLC (c) 2004-2018 |
b6708aeb 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+--------------------------------------------------------------------+
e70a7fc0 26 */
6a488035 27
6a488035
TO
28/**
29 * Test APIv3 civicrm_create_custom_group
30 *
6c6e6187 31 * @package CiviCRM
acb109b7 32 * @group headless
6a488035
TO
33 */
34class api_v3_CustomFieldTest extends CiviUnitTestCase {
35 protected $_apiversion;
b7c9bc4c 36
00be9182 37 public function setUp() {
6a488035
TO
38 $this->_apiversion = 3;
39 parent::setUp();
40 }
41
00be9182 42 public function tearDown() {
6a488035 43 $tablesToTruncate = array(
b3c30fda
CW
44 'civicrm_contact',
45 'civicrm_file',
46 'civicrm_entity_file',
6a488035 47 );
b3c30fda 48 // true tells quickCleanup to drop custom_value tables that might have been created in the test
6a488035
TO
49 $this->quickCleanup($tablesToTruncate, TRUE);
50 }
51
52 /**
eceb18cc 53 * Check with no array.
6a488035 54 */
00be9182 55 public function testCustomFieldCreateNoArray() {
6a488035
TO
56 $fieldParams = NULL;
57
d0e1eff2 58 $customField = $this->callAPIFailure('custom_field', 'create', $fieldParams);
6a488035
TO
59 $this->assertEquals($customField['error_message'], 'Input variable `params` is not an array');
60 }
61
62 /**
eceb18cc 63 * Check with no label.
6a488035 64 */
00be9182 65 public function testCustomFieldCreateWithoutLabel() {
e830c6ae 66 $customGroup = $this->customGroupCreate(array('extends' => 'Individual', 'title' => 'text_test_group'));
6a488035
TO
67 $params = array(
68 'custom_group_id' => $customGroup['id'],
69 'name' => 'test_textfield2',
70 'html_type' => 'Text',
71 'data_type' => 'String',
72 'default_value' => 'abc',
73 'weight' => 4,
74 'is_required' => 1,
75 'is_searchable' => 0,
76 'is_active' => 1,
6a488035
TO
77 );
78
d0e1eff2 79 $customField = $this->callAPIFailure('custom_field', 'create', $params);
6a488035
TO
80 $this->assertEquals($customField['error_message'], 'Mandatory key(s) missing from params array: label');
81 }
82
83 /**
eceb18cc 84 * Check with edit.
6a488035 85 */
00be9182 86 public function testCustomFieldCreateWithEdit() {
e830c6ae 87 $customGroup = $this->customGroupCreate(array('extends' => 'Individual', 'title' => 'text_test_group'));
6a488035
TO
88 $params = array(
89 'custom_group_id' => $customGroup['id'],
90 'name' => 'test_textfield2',
91 'label' => 'Name1',
92 'html_type' => 'Text',
93 'data_type' => 'String',
94 'default_value' => 'abc',
95 'weight' => 4,
96 'is_required' => 1,
97 'is_searchable' => 0,
98 'is_active' => 1,
6a488035
TO
99 );
100
92915c55 101 $customField = $this->callAPIAndDocument('custom_field', 'create', $params, __FUNCTION__, __FILE__);
6a488035 102 $params['id'] = $customField['id'];
92915c55 103 $customField = $this->callAPISuccess('custom_field', 'create', $params);
6a488035 104
ba4a1892 105 $this->assertNotNull($customField['id']);
6a488035
TO
106 }
107
108 /**
eceb18cc 109 * Check without groupId.
6a488035 110 */
00be9182 111 public function testCustomFieldCreateWithoutGroupID() {
6a488035
TO
112 $fieldParams = array(
113 'name' => 'test_textfield1',
114 'label' => 'Name',
115 'html_type' => 'Text',
116 'data_type' => 'String',
117 'default_value' => 'abc',
118 'weight' => 4,
119 'is_required' => 1,
120 'is_searchable' => 0,
121 'is_active' => 1,
e830c6ae 122
6a488035
TO
123 );
124
d0e1eff2 125 $customField = $this->callAPIFailure('custom_field', 'create', $fieldParams);
6a488035
TO
126 $this->assertEquals($customField['error_message'], 'Mandatory key(s) missing from params array: custom_group_id');
127 }
128
129 /**
130 * Check for Each data type: loop through available form input types
ae5ffbb7 131 */
00be9182 132 public function testCustomFieldCreateAllAvailableFormInputs() {
e830c6ae 133 $gid = $this->customGroupCreate(array('extends' => 'Individual', 'title' => 'testAllFormInputs'));
6a488035
TO
134
135 $dtype = CRM_Core_BAO_CustomField::dataType();
136 $htype = CRM_Core_BAO_CustomField::dataToHtml();
137
138 $n = 0;
139 foreach ($dtype as $dkey => $dvalue) {
140 foreach ($htype[$n] as $hkey => $hvalue) {
141 //echo $dkey."][".$hvalue."\n";
142 $this->_loopingCustomFieldCreateTest($this->_buildParams($gid['id'], $hvalue, $dkey));
143 }
144 $n++;
145 }
146 }
6c6e6187 147 /*
e70a7fc0
TO
148 * Can't figure out the point of this?
149 */
4cbe18b8 150 /**
c490a46a 151 * @param array $params
4cbe18b8 152 */
00be9182 153 public function _loopingCustomFieldCreateTest($params) {
e830c6ae 154 $customField = $this->callAPISuccess('custom_field', 'create', $params);
6a488035
TO
155 $this->assertNotNull($customField['id']);
156 $this->getAndCheck($params, $customField['id'], 'CustomField');
157 }
158
4cbe18b8 159 /**
100fef9d 160 * @param int $gid
4cbe18b8
EM
161 * @param $htype
162 * @param $dtype
163 *
164 * @return array
165 */
00be9182 166 public function _buildParams($gid, $htype, $dtype) {
6a488035
TO
167 $params = $this->_buildBasicParams($gid, $htype, $dtype);
168 /* //Not Working for any type. Maybe redundant with testCustomFieldCreateWithOptionValues()
e70a7fc0
TO
169 if ($htype == 'Multi-Select')
170 $params = array_merge($params, array(
171 'option_label' => array( 'Label1','Label2'),
172 'option_value' => array( 'val1', 'val2' ),
173 'option_weight' => array( 1, 2),
174 'option_status' => array( 1, 1),
175 ));
176 */
6a488035
TO
177
178 return $params;
179 }
180
4cbe18b8 181 /**
100fef9d 182 * @param int $gid
4cbe18b8
EM
183 * @param $htype
184 * @param $dtype
185 *
186 * @return array
187 */
00be9182 188 public function _buildBasicParams($gid, $htype, $dtype) {
6a488035
TO
189 return array(
190 'custom_group_id' => $gid,
191 'label' => $dtype . $htype,
192 'html_type' => $htype,
193 'data_type' => $dtype,
194 'weight' => 4,
195 'is_required' => 0,
196 'is_searchable' => 0,
197 'is_active' => 1,
e830c6ae 198
6a488035
TO
199 );
200 }
201
202 /**
eceb18cc 203 * Test using example code.
6a488035
TO
204 */
205 /*function testCustomFieldCreateExample( )
e70a7fc0 206 {
6a488035 207
e70a7fc0
TO
208 $customGroup = $this->customGroupCreate('Individual','date_test_group',3);
209 require_once 'api/v3/examples/CustomField/Create.php';
210 $result = custom_field_create_example();
211 $expectedResult = custom_field_create_expectedresult();
212 $this->assertEquals($result,$expectedResult);
213 }*/
6a488035
TO
214
215 /**
100fef9d 216 * Check with data type - Options with option_values
6a488035 217 */
00be9182 218 public function testCustomFieldCreateWithEmptyOptionGroup() {
e830c6ae 219 $customGroup = $this->customGroupCreate(array('extends' => 'Contact', 'title' => 'select_test_group'));
b958933f 220 $params = array(
221 'custom_group_id' => $customGroup['id'],
222 'label' => 'Country',
223 'html_type' => 'Select',
224 'data_type' => 'String',
225 'weight' => 4,
226 'is_required' => 1,
227 'is_searchable' => 0,
228 'is_active' => 1,
b958933f 229 );
230
e830c6ae 231 $customField = $this->callAPISuccess('custom_field', 'create', $params);
b958933f 232 $this->assertNotNull($customField['id']);
e830c6ae 233 $optionGroupID = $this->callAPISuccess('custom_field', 'getvalue', array(
b958933f 234 'id' => $customField['id'],
235 'return' => 'option_group_id',
236 ));
237
238 $this->assertTrue(is_numeric($optionGroupID) && ($optionGroupID > 0));
e830c6ae 239 $optionGroup = $this->callAPISuccess('option_group', 'getsingle', array(
ae5ffbb7 240 'id' => $optionGroupID,
92915c55 241 ));
6c6e6187 242 $this->assertEquals($optionGroup['title'], 'Country');
e830c6ae 243 $optionValueCount = $this->callAPISuccess('option_value', 'getcount', array(
ae5ffbb7 244 'option_group_id' => $optionGroupID,
92915c55 245 ));
b958933f 246 $this->assertEquals(0, $optionValueCount);
247 }
248
65c2fd15
JP
249 /**
250 * Check with non-ascii labels
251 */
252 public function testCustomFieldCreateWithNonAsciiLabel() {
253 $customGroup = $this->customGroupCreate(array('extends' => 'Contact', 'title' => 'select_test_group'));
254 $params = array(
255 'custom_group_id' => $customGroup['id'],
256 'label' => 'ôôôô',
257 'html_type' => 'Select',
258 'data_type' => 'String',
259 'weight' => 4,
260 'is_required' => 1,
261 'is_searchable' => 0,
262 'is_active' => 1,
263 );
264 $customField = $this->callAPISuccess('custom_field', 'create', $params);
265 $this->assertNotNull($customField['id']);
266 $params['label'] = 'ààà';
267 $customField = $this->callAPISuccess('custom_field', 'create', $params);
268 $this->assertNotNull($customField['id']);
269 }
270
eebb53df 271 /**
eceb18cc 272 * Test custom field with existing option group.
eebb53df 273 */
00be9182 274 public function testCustomFieldExistingOptionGroup() {
eebb53df
JV
275 $customGroup = $this->customGroupCreate(array('extends' => 'Organization', 'title' => 'test_group'));
276 $params = array(
277 'custom_group_id' => $customGroup['id'],
278 // Just to say something:
279 'label' => 'Organization Gender',
280 'html_type' => 'Select',
281 'data_type' => 'Int',
282 'weight' => 4,
283 'is_required' => 1,
284 'is_searchable' => 0,
285 'is_active' => 1,
286 // Option group id 3: gender
287 'option_group_id' => 3,
288 );
289
290 $customField = $this->callAPISuccess('custom_field', 'create', $params);
291 $this->assertNotNull($customField['id']);
292 $optionGroupID = $this->callAPISuccess('custom_field', 'getvalue', array(
293 'id' => $customField['id'],
294 'return' => 'option_group_id',
295 ));
296
6c6e6187 297 $this->assertEquals($optionGroupID, 3);
eebb53df
JV
298 }
299
3c70d501 300 /**
301 * Test custom field get works & return param works
302 */
9b873358 303 public function testCustomFieldGetReturnOptions() {
e830c6ae 304 $customGroup = $this->customGroupCreate(array('extends' => 'Individual', 'title' => 'test_group'));
b422b715 305 $customField = $this->customFieldCreate(array('custom_group_id' => $customGroup['id']));
3c70d501 306
e830c6ae 307 $result = $this->callAPISuccess('custom_field', 'getsingle', array(
3c70d501 308 'id' => $customField['id'],
309 'return' => 'data_type',
310 ));
311 $this->assertTrue(array_key_exists('data_type', $result));
312 $this->assertFalse(array_key_exists('custom_group_id', $result));
313 }
314
315 /**
316 * Test custom field get works & return param works
317 */
9b873358 318 public function testCustomFieldGetReturnArray() {
e830c6ae 319 $customGroup = $this->customGroupCreate(array('extends' => 'Individual', 'title' => 'test_group'));
b422b715 320 $customField = $this->customFieldCreate(array('custom_group_id' => $customGroup['id']));
3c70d501 321
e830c6ae 322 $result = $this->callAPISuccess('custom_field', 'getsingle', array(
92915c55 323 'id' => $customField['id'],
3c70d501 324 'return' => array('data_type'),
325 ));
326 $this->assertTrue(array_key_exists('data_type', $result));
327 $this->assertFalse(array_key_exists('custom_group_id', $result));
328 }
329
330 /**
331 * Test custom field get works & return param works
332 */
9b873358 333 public function testCustomFieldGetReturnTwoOptions() {
e830c6ae 334 $customGroup = $this->customGroupCreate(array('extends' => 'Individual', 'test_group'));
b422b715 335 $customField = $this->customFieldCreate(array('custom_group_id' => $customGroup['id']));
3c70d501 336
e830c6ae 337 $result = $this->callAPISuccess('custom_field', 'getsingle', array(
92915c55 338 'id' => $customField['id'],
3c70d501 339 'return' => 'data_type, custom_group_id',
340 ));
341 $this->assertTrue(array_key_exists('data_type', $result));
342 $this->assertTrue(array_key_exists('custom_group_id', $result));
343 $this->assertFalse(array_key_exists('label', $result));
344 }
345
00be9182 346 public function testCustomFieldCreateWithOptionValues() {
e830c6ae 347 $customGroup = $this->customGroupCreate(array('extends' => 'Contact', 'title' => 'select_test_group'));
6a488035
TO
348
349 $option_values = array(
6c6e6187 350 array(
92915c55 351 'weight' => 1,
6a488035
TO
352 'label' => 'Label1',
353 'value' => 1,
354 'is_active' => 1,
355 ),
356 array(
357 'weight' => 2,
358 'label' => 'Label2',
359 'value' => 2,
360 'is_active' => 1,
361 ),
362 );
363
364 $params = array(
365 'custom_group_id' => $customGroup['id'],
7f6d3dd3 366 'label' => 'Our special field',
6a488035
TO
367 'html_type' => 'Select',
368 'data_type' => 'String',
369 'weight' => 4,
370 'is_required' => 1,
371 'is_searchable' => 0,
372 'is_active' => 1,
373 'option_values' => $option_values,
e830c6ae 374
6a488035
TO
375 );
376
e830c6ae 377 $customField = $this->callAPISuccess('custom_field', 'create', $params);
6a488035 378
b958933f 379 $this->assertAPISuccess($customField);
6a488035
TO
380 $this->assertNotNull($customField['id']);
381 $getFieldsParams = array(
382 'options' => array('get_options' => 'custom_' . $customField['id']),
92915c55 383 'action' => 'create',
6a488035 384 );
5c49fee0 385 $description = "Demonstrates retrieving metadata with custom field options.";
6a488035 386 $subfile = "GetFieldsOptions";
a828d7b8 387 $fields = $this->callAPIAndDocument('contact', 'getfields', $getFieldsParams, __FUNCTION__, 'ContactTest.php', $description, $subfile);
6a488035
TO
388 $this->assertArrayHasKey('options', $fields['values']['custom_' . $customField['id']]);
389 $this->assertEquals('Label1', $fields['values']['custom_' . $customField['id']]['options'][1]);
390 $getOptionsArray = array(
391 'field' => 'custom_' . $customField['id'],
92915c55 392 );
5c49fee0 393 $description = "Demonstrates retrieving options for a custom field.";
6a488035 394 $subfile = "GetOptions";
a828d7b8 395 $result = $this->callAPIAndDocument('contact', 'getoptions', $getOptionsArray, __FUNCTION__, 'ContactTest.php', $description, '');
6a488035 396 $this->assertEquals('Label1', $result['values'][1]);
6a488035
TO
397 }
398
399 ///////////////// civicrm_custom_field_delete methods
400
401 /**
eceb18cc 402 * Check with no array.
6a488035 403 */
00be9182 404 public function testCustomFieldDeleteNoArray() {
6a488035 405 $params = NULL;
d0e1eff2 406 $customField = $this->callAPIFailure('custom_field', 'delete', $params);
6a488035
TO
407 $this->assertEquals($customField['error_message'], 'Input variable `params` is not an array');
408 }
409
410 /**
eceb18cc 411 * Check without Field ID.
6a488035 412 */
00be9182 413 public function testCustomFieldDeleteWithoutFieldID() {
e830c6ae 414 $params = array();
415 $customField = $this->callAPIFailure('custom_field', 'delete', $params,
416 'Mandatory key(s) missing from params array: id');
6a488035
TO
417 }
418
419 /**
eceb18cc 420 * Check without valid array.
6a488035 421 */
00be9182 422 public function testCustomFieldDelete() {
e830c6ae 423 $customGroup = $this->customGroupCreate(array('extends' => 'Individual', 'title' => 'test_group'));
b422b715 424 $customField = $this->customFieldCreate(array('custom_group_id' => $customGroup['id']));
ba4a1892 425 $this->assertNotNull($customField['id']);
6a488035
TO
426
427 $params = array(
6a488035
TO
428 'id' => $customField['id'],
429 );
e830c6ae 430 $result = $this->callAPIAndDocument('custom_field', 'delete', $params, __FUNCTION__, __FILE__);
6a488035 431
a15773db 432 $this->assertAPISuccess($result);
6a488035
TO
433 }
434
435 /**
eceb18cc 436 * Check for Option Value.
6a488035 437 */
00be9182 438 public function testCustomFieldOptionValueDelete() {
e830c6ae 439 $customGroup = $this->customGroupCreate(array('extends' => 'Contact', 'title' => 'ABC'));
6a488035 440 $customOptionValueFields = $this->customFieldOptionValueCreate($customGroup, 'fieldABC');
6a488035 441 $params = array(
6a488035
TO
442 'id' => $customOptionValueFields,
443 );
444
e830c6ae 445 $customField = $this->callAPISuccess('custom_field', 'delete', $customOptionValueFields);
6a488035 446 }
6b59896e
TO
447
448 /**
449 * If there's one custom group for "Contact" and one for "Activity", then "Contact.getfields"
450 * and "Activity.getfields" should return only their respective fields (not the other's fields),
451 * and unrelated entities should return no custom fields.
452 */
00be9182 453 public function testGetfields_CrossEntityPollution() {
6b59896e
TO
454 $auxEntities = array('Email', 'Address', 'LocBlock', 'Membership', 'ContributionPage', 'ReportInstance');
455 $allEntities = array_merge(array('Contact', 'Activity'), $auxEntities);
456
457 // Baseline - getfields doesn't reporting any customfields for any entities
458 foreach ($allEntities as $entity) {
459 $this->assertEquals(
460 array(),
461 $this->getCustomFieldKeys($this->callAPISuccess($entity, 'getfields', array())),
462 "Baseline custom fields for $entity should be empty"
463 );
464 }
465
466 // Add some fields
f8a3cd29 467 $contactGroup = $this->customGroupCreate(array('extends' => 'Contact', 'title' => 'test_group_c'));
92915c55
TO
468 $contactField = $this->customFieldCreate(array(
469 'custom_group_id' => $contactGroup['id'],
ae5ffbb7 470 'label' => 'For Contacts',
92915c55 471 ));
f8a3cd29
TO
472 $indivGroup = $this->customGroupCreate(array('extends' => 'Individual', 'title' => 'test_group_i'));
473 $indivField = $this->customFieldCreate(array('custom_group_id' => $indivGroup['id'], 'label' => 'For Individuals'));
474 $activityGroup = $this->customGroupCreate(array('extends' => 'Activity', 'title' => 'test_group_a'));
92915c55
TO
475 $activityField = $this->customFieldCreate(array(
476 'custom_group_id' => $activityGroup['id'],
ae5ffbb7 477 'label' => 'For Activities',
92915c55 478 ));
6b59896e 479
f8a3cd29
TO
480 // Check getfields
481 $this->assertEquals(
482 array('custom_' . $contactField['id'], 'custom_' . $indivField['id']),
483 $this->getCustomFieldKeys($this->callAPISuccess('Contact', 'getfields', array())),
484 'Contact custom fields'
485 );
486 $this->assertEquals(
487 array('custom_' . $contactField['id'], 'custom_' . $indivField['id']),
488 $this->getCustomFieldKeys($this->callAPISuccess('Individual', 'getfields', array())),
489 'Individual custom fields'
490 );
491 $this->assertEquals(
492 array('custom_' . $contactField['id']),
493 $this->getCustomFieldKeys($this->callAPISuccess('Organization', 'getfields', array())),
494 'Organization custom fields'
495 );
6b59896e
TO
496 $this->assertEquals(
497 array('custom_' . $activityField['id']),
498 $this->getCustomFieldKeys($this->callAPISuccess('Activity', 'getfields', array())),
499 'Activity custom fields'
500 );
501 foreach ($auxEntities as $entity) {
502 $this->assertEquals(
503 array(),
504 $this->getCustomFieldKeys($this->callAPISuccess($entity, 'getfields', array())),
505 "Custom fields for $entity should be empty"
506 );
507 }
508 }
509
b3c30fda
CW
510 /**
511 * Test setting and getting a custom file field value.
512 *
513 * Uses the "attachment" api for setting value.
514 */
515 public function testCustomFileField() {
516 $customGroup = $this->customGroupCreate(array('title' => 'attachment_test_group'));
517 $params = array(
518 'custom_group_id' => $customGroup['id'],
519 'name' => 'test_file_attachment',
520 'label' => 'test_file_attachment',
521 'html_type' => 'File',
522 'data_type' => 'File',
523 'is_active' => 1,
524 );
525 $customField = $this->callAPISuccess('custom_field', 'create', $params);
526 $cfId = 'custom_' . $customField['id'];
527
528 $cid = $this->individualCreate();
529
530 $attachment = $this->callAPISuccess('attachment', 'create', array(
531 'name' => CRM_Utils_String::createRandom(5, CRM_Utils_String::ALPHANUMERIC) . '_testCustomFileField.txt',
532 'mime_type' => 'text/plain',
533 'content' => 'My test content',
534 'field_name' => $cfId,
535 'entity_id' => $cid,
536 ));
537 $this->assertAttachmentExistence(TRUE, $attachment);
538
539 $result = $this->callAPISuccess('contact', 'getsingle', array(
540 'id' => $cid,
541 'return' => $cfId,
542 ));
543
544 $this->assertEquals($attachment['id'], $result[$cfId]);
545 }
546
12b07b22
MD
547 public function testUpdateCustomField() {
548 $customGroup = $this->customGroupCreate(array('extends' => 'Individual'));
549 $params = array('id' => $customGroup['id'], 'is_active' => 0);
550 $result = $this->callAPISuccess('CustomGroup', 'create', $params);
551 $result = array_shift($result['values']);
552
553 $this->assertEquals(0, $result['is_active']);
554
555 $this->customGroupDelete($customGroup['id']);
556 }
557
4cbe18b8
EM
558 /**
559 * @param $getFieldsResult
560 *
561 * @return array
562 */
00be9182 563 public function getCustomFieldKeys($getFieldsResult) {
92915c55 564 $isCustom = function ($key) {
6b59896e
TO
565 return preg_match('/^custom_/', $key);
566 };
f8a3cd29
TO
567 $r = array_values(array_filter(array_keys($getFieldsResult['values']), $isCustom));
568 sort($r);
569 return $r;
6b59896e 570 }
96025800 571
6a488035 572}