3 use Civi\Api4\CustomField
;
6 * Class CRM_Core_BAO_CustomFieldTest
10 class CRM_Core_BAO_CustomFieldTest
extends CiviUnitTestCase
{
12 use CRMTraits_Custom_CustomDataTrait
;
14 protected $customFieldID;
17 * Clean up after test.
21 public function tearDown(): void
{
22 $this->quickCleanup([], TRUE);
27 * Test creating a custom field.
29 public function testCreateCustomField() {
30 $customGroup = $this->createCustomField();
31 $customFieldID = $this->assertDBNotNull('CRM_Core_DAO_CustomField', $customGroup['id'], 'id', 'custom_group_id',
32 'Database check for created CustomField.'
35 'id' => $customFieldID,
36 'label' => 'editTestFld',
38 'data_type' => 'String',
39 'html_type' => 'Text',
40 'custom_group_id' => $customGroup['id'],
43 CRM_Core_BAO_CustomField
::create($fields);
44 $this->assertDBNotNull('CRM_Core_DAO_CustomField', 1, 'id', 'is_active', 'Database check for edited CustomField.');
45 $this->assertDBNotNull('CRM_Core_DAO_CustomField', $fields['label'], 'id', 'label', 'Database check for edited CustomField.');
47 $dbFieldName = $this->assertDBNotNull('CRM_Core_DAO_CustomField', $customFieldID, 'name', 'id', 'Database check for edited CustomField.');
48 $dbColumnName = $this->assertDBNotNull('CRM_Core_DAO_CustomField', $customFieldID, 'column_name', 'id', 'Database check for edited CustomField.');
49 $this->assertEquals(strtolower("{$dbFieldName}_{$customFieldID}"), $dbColumnName,
50 "Column name ends in ID");
52 $this->customGroupDelete($customGroup['id']);
56 * Test changing a data type from multiple-choice to Text.
58 public function testChangeDataType() {
59 $customGroup = $this->createCustomField();
61 'label' => 'Radio to Text',
63 'data_type' => 'String',
64 'html_type' => 'Radio',
65 'custom_group_id' => $customGroup['id'],
67 'option_label' => ["One", "Two"],
68 'option_value' => [1, 2],
69 'option_weight' => [1, 2],
70 'option_status' => [1, 1],
72 $customField = CRM_Core_BAO_CustomField
::create($fields);
73 $this->assertNotNull($customField->option_group_id
);
75 'id' => $customField->id
,
76 'html_type' => 'Text',
77 'custom_group_id' => $customGroup['id'],
79 $customFieldModified = CRM_Core_BAO_CustomField
::create($fieldsNew);
80 $this->assertFalse($customFieldModified->option_group_id ??
FALSE);
84 * Test custom field create accepts passed column name.
86 public function testCreateCustomFieldColumnName() {
87 $customGroup = $this->customGroupCreate(['extends' => 'Individual']);
89 'label' => 'testFld 2',
90 'column_name' => 'special_colname',
91 'data_type' => 'String',
92 'html_type' => 'Text',
93 'custom_group_id' => $customGroup['id'],
95 CRM_Core_BAO_CustomField
::create($fields);
96 $customFieldID = $this->assertDBNotNull('CRM_Core_DAO_CustomField', $customGroup['id'], 'id', 'custom_group_id',
97 'Database check for created CustomField.'
99 $dbColumnName = $this->assertDBNotNull('CRM_Core_DAO_CustomField', $customFieldID, 'column_name', 'id', 'Database check for edited CustomField.');
100 $this->assertEquals($fields['column_name'], $dbColumnName,
101 "Column name set as specified");
103 $this->customGroupDelete($customGroup['id']);
107 * Test that name is used for the column.
109 public function testCreateCustomFieldName() {
110 $customGroup = $this->customGroupCreate(['extends' => 'Individual']);
112 'label' => 'testFld 2',
113 'name' => 'special_fldlname',
114 'data_type' => 'String',
115 'html_type' => 'Text',
116 'custom_group_id' => $customGroup['id'],
118 CRM_Core_BAO_CustomField
::create($fields);
119 $customFieldID = $this->assertDBNotNull('CRM_Core_DAO_CustomField', $customGroup['id'], 'id', 'custom_group_id',
120 'Database check for created CustomField.'
122 $dbFieldName = $this->assertDBNotNull('CRM_Core_DAO_CustomField', $customFieldID, 'name', 'id', 'Database check for edited CustomField.');
123 $this->assertEquals($fields['name'], $dbFieldName,
124 "Column name set as specified");
126 $this->customGroupDelete($customGroup['id']);
130 * Test get fields function.
132 public function testGetFields() {
133 $customGroup = $this->customGroupCreate(['extends' => 'Individual']);
135 'label' => 'testFld1',
136 'data_type' => 'String',
137 'html_type' => 'Text',
139 'custom_group_id' => $customGroup['id'],
141 CRM_Core_BAO_CustomField
::create($fields);
142 $this->assertDBNotNull('CRM_Core_DAO_CustomField', $customGroup['id'], 'id', 'custom_group_id',
143 'Database check for created CustomField.'
146 'label' => 'testFld2',
147 'data_type' => 'String',
148 'html_type' => 'Text',
150 'custom_group_id' => $customGroup['id'],
152 CRM_Core_BAO_CustomField
::create($fields);
153 $this->assertDBNotNull('CRM_Core_DAO_CustomField', $customGroup['id'], 'id', 'custom_group_id',
154 'Database check for created CustomField.'
157 $this->customGroupDelete($customGroup['id']);
163 public function testGetDisplayedValues() {
164 $customGroup = $this->customGroupCreate(['extends' => 'Individual']);
167 'data_type' => 'Country',
168 'html_type' => 'Select',
170 'United States' => 1228,
175 'data_type' => 'StateProvince',
176 'html_type' => 'Select',
181 'Alabama, Alaska' => [1000, 1001],
185 'data_type' => 'String',
186 'html_type' => 'Radio',
195 'data_type' => 'String',
196 'html_type' => 'CheckBox',
204 'Label1' => ['key1'],
206 'Label2, Label3' => ['key2', 'key3'],
207 'Label3, Label4' => CRM_Utils_Array
::implodePadded(['key3', 'key4']),
208 'Label1, Label4' => ['key1' => 1, 'key4' => 1],
212 'data_type' => 'Date',
213 'html_type' => 'Select Date',
214 'date_format' => 'd M yy',
217 '1 Jun 1999 1:30PM' => '1999-06-01 13:30',
222 'data_type' => 'Money',
223 'html_type' => 'Radio',
226 '10.1' => '10.1 USD',
227 '10.99' => '10.99 USD',
231 '10.1 USD' => '10.10',
232 '10.99 USD' => '10.99',
236 foreach ($fieldsToCreate as $num => $field) {
237 $params = $field +
['label' => 'test field ' . $num, 'custom_group_id' => $customGroup['id']];
238 unset($params['tests']);
239 $createdField = $this->callAPISuccess('customField', 'create', $params);
240 foreach ($field['tests'] as $expected => $input) {
241 $this->assertEquals($expected, CRM_Core_BAO_CustomField
::displayValue($input, $createdField['id']));
245 $this->customGroupDelete($customGroup['id']);
249 * Test CRM_Core_BAO_CustomField::displayValue.
251 * @throws \CRM_Core_Exception
254 public function testGetDisplayedValuesContactRef() {
255 $customGroup = $this->customGroupCreate(['extends' => 'Individual']);
257 'data_type' => 'ContactReference',
258 'html_type' => 'Autocomplete-Select',
259 'label' => 'test ref',
260 'custom_group_id' => $customGroup['id'],
262 $createdField = $this->callAPISuccess('customField', 'create', $params);
263 $contact1 = $this->individualCreate();
264 $contact2 = $this->individualCreate(['custom_' . $createdField['id'] => $contact1]);
265 $contact1Details = $this->callAPISuccess('Contact', 'getsingle', ['id' => $contact1]);
266 $this->assertEquals($contact1Details['display_name'], CRM_Core_BAO_CustomField
::displayValue($contact2, $createdField['id']));
267 $this->assertEquals("Bob", CRM_Core_BAO_CustomField
::displayValue("Bob", $createdField['id']));
269 $this->contactDelete($contact2);
270 $this->contactDelete($contact1);
271 $this->customGroupDelete($customGroup['id']);
274 public function testDeleteCustomField() {
275 $customGroup = $this->customGroupCreate(['extends' => 'Individual']);
277 'custom_group_id' => $customGroup['id'],
278 'label' => 'Throwaway Field',
279 'dataType' => 'Memo',
280 'htmlType' => 'TextArea',
283 $customField = $this->customFieldCreate($fields);
284 $fieldObject = new CRM_Core_BAO_CustomField();
285 $fieldObject->id
= $customField['id'];
286 $fieldObject->find(TRUE);
287 CRM_Core_BAO_CustomField
::deleteField($fieldObject);
288 $this->assertDBNull('CRM_Core_DAO_CustomField', $customGroup['id'], 'id',
289 'custom_group_id', 'Database check for deleted Custom Field.'
291 $this->customGroupDelete($customGroup['id']);
295 * Move a custom field from $groupA to $groupB.
297 * Make sure that data records are correctly matched and created.
299 * @throws \CRM_Core_Exception
301 public function testMoveField() {
302 $countriesByName = array_flip(CRM_Core_PseudoConstant
::country(FALSE, FALSE));
303 $this->assertTrue($countriesByName['Andorra'] > 0);
305 'A' => $this->customGroupCreate([
306 'title' => 'Test_Group A',
307 'name' => 'test_group_a',
308 'extends' => ['Individual'],
314 'B' => $this->customGroupCreate([
315 'title' => 'Test_Group B',
316 'name' => 'test_group_b',
317 'extends' => ['Individual'],
324 $groupA = $groups['A']['values'][$groups['A']['id']];
325 $groupB = $groups['B']['values'][$groups['B']['id']];
326 $countryA = $this->customFieldCreate([
327 'custom_group_id' => $groups['A']['id'],
328 'label' => 'Country A',
329 'dataType' => 'Country',
330 'htmlType' => 'Select',
331 'default_value' => NULL,
333 $countryB = $this->customFieldCreate([
334 'custom_group_id' => $groups['A']['id'],
335 'label' => 'Country B',
336 'dataType' => 'Country',
337 'htmlType' => 'Select',
338 'default_value' => NULL,
340 $countryC = $this->customFieldCreate([
341 'custom_group_id' => $groups['B']['id'],
342 'label' => 'Country C',
343 'dataType' => 'Country',
344 'htmlType' => 'Select',
345 'default_value' => NULL,
349 'countryA' => $countryA['values'][$countryA['id']],
350 'countryB' => $countryB['values'][$countryB['id']],
351 'countryC' => $countryC['values'][$countryC['id']],
354 'alice' => $this->individualCreate([
355 'first_name' => 'Alice',
356 'last_name' => 'Albertson',
357 'custom_' . $fields['countryA']['id'] => $countriesByName['Andorra'],
358 'custom_' . $fields['countryB']['id'] => $countriesByName['Barbados'],
360 'bob' => $this->individualCreate([
361 'first_name' => 'Bob',
362 'last_name' => 'Roberts',
363 'custom_' . $fields['countryA']['id'] => $countriesByName['Austria'],
364 'custom_' . $fields['countryB']['id'] => $countriesByName['Bermuda'],
365 'custom_' . $fields['countryC']['id'] => $countriesByName['Chad'],
367 'carol' => $this->individualCreate([
368 'first_name' => 'Carol',
369 'last_name' => 'Carolson',
370 'custom_' . $fields['countryC']['id'] => $countriesByName['Cambodia'],
375 CRM_Core_BAO_CustomField
::moveField($fields['countryB']['id'], $groupB['id']);
377 // Group[A] no longer has fields[countryB]
379 $this->assertDBQuery(1, "SELECT {$fields['countryB']['column_name']} FROM " . $groupA['table_name']);
380 $this->fail('Expected exception when querying column on wrong table');
382 catch (PEAR_Exception
$e) {
386 // Alice: Group[B] has fields[countryB], but fields[countryC] did not exist before
387 $this->assertDBQuery(1,
388 "SELECT count(*) FROM {$groupB['table_name']}
390 AND {$fields['countryB']['column_name']} = %3
391 AND {$fields['countryC']['column_name']} is null",
393 1 => [$contacts['alice'], 'Integer'],
394 3 => [$countriesByName['Barbados'], 'Integer'],
398 // Bob: Group[B] has merged fields[countryB] and fields[countryC] on the same record
399 $this->assertDBQuery(1,
400 "SELECT count(*) FROM {$groupB['table_name']}
402 AND {$fields['countryB']['column_name']} = %3
403 AND {$fields['countryC']['column_name']} = %4",
405 1 => [$contacts['bob'], 'Integer'],
406 3 => [$countriesByName['Bermuda'], 'Integer'],
407 4 => [$countriesByName['Chad'], 'Integer'],
411 // Carol: Group[B] still has fields[countryC] but did not get fields[countryB]
412 $this->assertDBQuery(1,
413 "SELECT count(*) FROM {$groupB['table_name']}
415 AND {$fields['countryB']['column_name']} is null
416 AND {$fields['countryC']['column_name']} = %4",
418 1 => [$contacts['carol'], 'Integer'],
419 4 => [$countriesByName['Cambodia'], 'Integer'],
423 $this->customGroupDelete($groups['A']['id']);
424 $this->customGroupDelete($groupB['id']);
428 * Test get custom field id function.
430 * @throws \CiviCRM_API3_Exception
432 public function testGetCustomFieldID() {
433 $this->createCustomField();
434 $fieldID = CRM_Core_BAO_CustomField
::getCustomFieldID('testFld');
435 $this->assertEquals($this->customFieldID
, $fieldID);
437 $fieldID = CRM_Core_BAO_CustomField
::getCustomFieldID('testFld', 'new custom group');
438 $this->assertEquals($this->customFieldID
, $fieldID);
440 $fieldID = CRM_Core_BAO_CustomField
::getCustomFieldID('testFld', 'new custom group', TRUE);
441 $this->assertEquals('custom_' . $this->customFieldID
, $fieldID);
443 // create field with same name in a different group
444 $this->createCustomField('other custom group');
445 $otherFieldID = CRM_Core_BAO_CustomField
::getCustomFieldID('testFld', 'other custom group');
446 // make sure it does not return the field ID of the first field
447 $this->assertNotEquals($fieldID, $otherFieldID);
451 * Create a custom field
453 * @param string $groupTitle
457 protected function createCustomField($groupTitle = 'new custom group') {
458 $customGroup = $this->customGroupCreate([
459 'extends' => 'Individual',
460 'title' => $groupTitle,
463 'label' => 'testFld',
464 'data_type' => 'String',
465 'html_type' => 'Text',
466 'custom_group_id' => $customGroup['id'],
468 $field = CRM_Core_BAO_CustomField
::create($fields);
469 $this->customFieldID
= $field->id
;
474 * Test the getFieldsForImport function.
478 public function testGetFieldsForImport() {
479 $this->entity
= 'Contact';
480 $this->createCustomGroupWithFieldsOfAllTypes();
481 $customGroupID = $this->ids
['CustomGroup']['Custom Group'];
483 $this->getCustomFieldName('country') => [
484 'name' => $this->getCustomFieldName('country'),
486 'title' => 'Country',
487 'headerPattern' => '//',
489 'custom_field_id' => $this->getCustomFieldID('country'),
490 'options_per_line' => NULL,
491 'text_length' => NULL,
492 'data_type' => 'Country',
493 'html_type' => 'Select',
494 'is_search_range' => '0',
495 'id' => $this->getCustomFieldID('country'),
496 'label' => 'Country',
497 'groupTitle' => 'Custom Group',
498 'default_value' => NULL,
499 'custom_group_id' => $customGroupID,
500 'extends' => 'Contact',
501 'extends_entity_column_value' => NULL,
502 'extends_entity_column_id' => NULL,
504 'is_multiple' => '0',
505 'option_group_id' => NULL,
506 'date_format' => NULL,
507 'time_format' => NULL,
509 'table_name' => 'civicrm_value_custom_group_' . $customGroupID,
510 'column_name' => $this->getCustomFieldColumnName('country'),
511 'where' => 'civicrm_value_custom_group_' . $customGroupID . '.' . $this->getCustomFieldColumnName('country'),
512 'extends_table' => 'civicrm_contact',
513 'search_table' => 'contact_a',
515 'pseudoconstant' => [
516 'table' => 'civicrm_country',
518 'labelColumn' => 'name',
519 'nameColumn' => 'iso_code',
522 $this->getCustomFieldName('multi_country') => [
523 'name' => $this->getCustomFieldName('multi_country'),
525 'title' => 'Country-multi',
526 'headerPattern' => '//',
528 'custom_field_id' => $this->getCustomFieldID('multi_country'),
529 'options_per_line' => NULL,
530 'text_length' => NULL,
531 'data_type' => 'Country',
532 'html_type' => 'Select',
533 'is_search_range' => '0',
534 'id' => $this->getCustomFieldID('multi_country'),
535 'label' => 'Country-multi',
536 'groupTitle' => 'Custom Group',
537 'default_value' => NULL,
538 'custom_group_id' => $customGroupID,
539 'extends' => 'Contact',
540 'extends_entity_column_value' => NULL,
541 'extends_entity_column_id' => NULL,
543 'is_multiple' => '0',
544 'option_group_id' => NULL,
545 'date_format' => NULL,
546 'time_format' => NULL,
548 'table_name' => 'civicrm_value_custom_group_' . $customGroupID,
549 'column_name' => $this->getCustomFieldColumnName('multi_country'),
550 'where' => 'civicrm_value_custom_group_' . $customGroupID . '.' . $this->getCustomFieldColumnName('multi_country'),
551 'extends_table' => 'civicrm_contact',
552 'search_table' => 'contact_a',
554 'pseudoconstant' => [
555 'table' => 'civicrm_country',
557 'labelColumn' => 'name',
558 'nameColumn' => 'iso_code',
561 $this->getCustomFieldName('file') => [
562 'name' => $this->getCustomFieldName('file'),
564 'title' => 'My file',
565 'headerPattern' => '//',
567 'custom_field_id' => $this->getCustomFieldID('file'),
568 'options_per_line' => NULL,
569 'text_length' => NULL,
570 'data_type' => 'File',
571 'html_type' => 'File',
572 'is_search_range' => '0',
573 'id' => $this->getCustomFieldID('file'),
574 'label' => 'My file',
575 'groupTitle' => 'Custom Group',
576 'default_value' => NULL,
577 'custom_group_id' => $customGroupID,
578 'extends' => 'Contact',
579 'extends_entity_column_value' => NULL,
580 'extends_entity_column_id' => NULL,
582 'is_multiple' => '0',
583 'option_group_id' => NULL,
584 'date_format' => NULL,
585 'time_format' => NULL,
587 'table_name' => 'civicrm_value_custom_group_' . $customGroupID,
588 'column_name' => 'my_file_' . $this->getCustomFieldID('file'),
589 'where' => 'civicrm_value_custom_group_' . $customGroupID . '.my_file_' . $this->getCustomFieldID('file'),
590 'extends_table' => 'civicrm_contact',
591 'search_table' => 'contact_a',
594 $this->getCustomFieldName('text') => [
595 'name' => $this->getCustomFieldName('text'),
597 'title' => 'Enter text here',
598 'headerPattern' => '//',
600 'custom_field_id' => $this->getCustomFieldID('text'),
601 'options_per_line' => NULL,
602 'text_length' => 300,
603 'data_type' => 'String',
604 'html_type' => 'Text',
605 'is_search_range' => '0',
606 'id' => $this->getCustomFieldID('text'),
607 'label' => 'Enter text here',
608 'groupTitle' => 'Custom Group',
609 'default_value' => 'xyz',
610 'custom_group_id' => $customGroupID,
611 'extends' => 'Contact',
612 'extends_entity_column_value' => NULL,
613 'extends_entity_column_id' => NULL,
615 'is_multiple' => '0',
616 'option_group_id' => NULL,
617 'date_format' => NULL,
618 'time_format' => NULL,
620 'table_name' => 'civicrm_value_custom_group_' . $customGroupID,
621 'column_name' => 'enter_text_here_' . $this->getCustomFieldID('text'),
622 'where' => 'civicrm_value_custom_group_' . $customGroupID . '.enter_text_here_' . $this->getCustomFieldID('text'),
623 'extends_table' => 'civicrm_contact',
624 'search_table' => 'contact_a',
628 $this->getCustomFieldName('select_string') => [
629 'name' => $this->getCustomFieldName('select_string'),
631 'title' => 'Pick Color',
632 'headerPattern' => '//',
634 'custom_field_id' => $this->getCustomFieldID('select_string'),
635 'options_per_line' => NULL,
636 'text_length' => NULL,
637 'data_type' => 'String',
638 'html_type' => 'Select',
639 'is_search_range' => '0',
640 'id' => $this->getCustomFieldID('select_string'),
641 'label' => 'Pick Color',
642 'groupTitle' => 'Custom Group',
643 'default_value' => NULL,
644 'custom_group_id' => $customGroupID,
645 'extends' => 'Contact',
646 'extends_entity_column_value' => NULL,
647 'extends_entity_column_id' => NULL,
649 'is_multiple' => '0',
650 'option_group_id' => $this->getOptionGroupID('select_string'),
651 'date_format' => NULL,
652 'time_format' => NULL,
654 'table_name' => 'civicrm_value_custom_group_' . $customGroupID,
655 'column_name' => 'pick_color_' . $this->getCustomFieldID('select_string'),
656 'where' => 'civicrm_value_custom_group_' . $customGroupID . '.pick_color_' . $this->getCustomFieldID('select_string'),
657 'extends_table' => 'civicrm_contact',
658 'search_table' => 'contact_a',
660 'pseudoconstant' => [
661 'optionGroupName' => $this->callAPISuccessGetValue('CustomField', ['id' => $this->getCustomFieldID('select_string'), 'return' => 'option_group_id.name']),
662 'optionEditPath' => 'civicrm/admin/options/' . $this->callAPISuccessGetValue('CustomField', ['id' => $this->getCustomFieldID('select_string'), 'return' => 'option_group_id.name']),
665 $this->getCustomFieldName('select_date') => [
666 'name' => $this->getCustomFieldName('select_date'),
668 'title' => 'Test Date',
669 'headerPattern' => '//',
671 'custom_field_id' => $this->getCustomFieldID('select_date'),
672 'options_per_line' => NULL,
673 'text_length' => NULL,
674 'data_type' => 'Date',
675 'html_type' => 'Select Date',
676 'is_search_range' => '1',
677 'date_format' => 'mm/dd/yy',
678 'time_format' => '1',
679 'id' => $this->getCustomFieldID('select_date'),
680 'label' => 'Test Date',
681 'groupTitle' => 'Custom Group',
682 'default_value' => '20090711',
683 'custom_group_id' => $customGroupID,
684 'extends' => 'Contact',
685 'extends_entity_column_value' => NULL,
686 'extends_entity_column_id' => NULL,
688 'is_multiple' => '0',
689 'option_group_id' => NULL,
690 'is_required' => '0',
691 'table_name' => 'civicrm_value_custom_group_' . $customGroupID,
692 'column_name' => 'test_date_' . $this->getCustomFieldID('select_date'),
693 'where' => 'civicrm_value_custom_group_' . $customGroupID . '.test_date_' . $this->getCustomFieldID('select_date'),
694 'extends_table' => 'civicrm_contact',
695 'search_table' => 'contact_a',
698 $this->getCustomFieldName('link') => [
699 'name' => $this->getCustomFieldName('link'),
701 'title' => 'test_link',
702 'headerPattern' => '//',
704 'custom_field_id' => $this->getCustomFieldID('link'),
705 'options_per_line' => NULL,
706 'text_length' => NULL,
707 'data_type' => 'Link',
708 'html_type' => 'Link',
709 'is_search_range' => '0',
710 'id' => $this->getCustomFieldID('link'),
711 'label' => 'test_link',
712 'groupTitle' => 'Custom Group',
713 'default_value' => 'http://civicrm.org',
714 'custom_group_id' => $customGroupID,
715 'extends' => 'Contact',
716 'extends_entity_column_value' => NULL,
717 'extends_entity_column_id' => NULL,
719 'is_multiple' => '0',
720 'option_group_id' => NULL,
721 'date_format' => NULL,
722 'time_format' => NULL,
724 'table_name' => 'civicrm_value_custom_group_' . $customGroupID,
725 'column_name' => 'test_link_' . $this->getCustomFieldID('link'),
726 'where' => 'civicrm_value_custom_group_' . $customGroupID . '.test_link_' . $this->getCustomFieldID('link'),
727 'extends_table' => 'civicrm_contact',
728 'search_table' => 'contact_a',
731 $this->getCustomFieldName('int') => [
732 'name' => $this->getCustomFieldName('int'),
733 'type' => CRM_Utils_Type
::T_INT
,
734 'title' => 'Enter integer here',
735 'headerPattern' => '//',
737 'custom_field_id' => $this->getCustomFieldID('int'),
738 'options_per_line' => NULL,
739 'text_length' => NULL,
740 'data_type' => 'Int',
741 'html_type' => 'Text',
742 'is_search_range' => '1',
743 'id' => $this->getCustomFieldID('int'),
744 'label' => 'Enter integer here',
745 'groupTitle' => 'Custom Group',
746 'default_value' => '4',
747 'custom_group_id' => $customGroupID,
748 'extends' => 'Contact',
749 'extends_entity_column_value' => NULL,
750 'extends_entity_column_id' => NULL,
752 'is_multiple' => '0',
753 'option_group_id' => NULL,
754 'date_format' => NULL,
755 'time_format' => NULL,
757 'table_name' => 'civicrm_value_custom_group_' . $customGroupID,
758 'column_name' => $this->getCustomFieldColumnName('int'),
759 'where' => 'civicrm_value_custom_group_' . $customGroupID . '.' . $this->getCustomFieldColumnName('int'),
760 'extends_table' => 'civicrm_contact',
761 'search_table' => 'contact_a',
764 $this->getCustomFieldName('contact_reference') => [
765 'name' => $this->getCustomFieldName('contact_reference'),
766 'type' => CRM_Utils_Type
::T_INT
,
767 'title' => 'Contact reference field',
768 'headerPattern' => '//',
770 'custom_field_id' => $this->getCustomFieldID('contact_reference'),
771 'options_per_line' => NULL,
772 'text_length' => NULL,
773 'data_type' => 'ContactReference',
774 'html_type' => 'Autocomplete-Select',
775 'is_search_range' => '0',
776 'id' => $this->getCustomFieldID('contact_reference'),
777 'label' => 'Contact reference field',
778 'groupTitle' => 'Custom Group',
779 'default_value' => NULL,
780 'custom_group_id' => $customGroupID,
781 'extends' => 'Contact',
782 'extends_entity_column_value' => NULL,
783 'extends_entity_column_id' => NULL,
785 'is_multiple' => '0',
786 'option_group_id' => NULL,
787 'date_format' => NULL,
788 'time_format' => NULL,
790 'table_name' => 'civicrm_value_custom_group_' . $customGroupID,
791 'column_name' => $this->getCustomFieldColumnName('contact_reference'),
792 'where' => 'civicrm_value_custom_group_' . $customGroupID . '.' . $this->getCustomFieldColumnName('contact_reference'),
793 'extends_table' => 'civicrm_contact',
794 'search_table' => 'contact_a',
797 $this->getCustomFieldName('state') => [
798 'name' => $this->getCustomFieldName('state'),
799 'id' => $this->getCustomFieldID('state'),
801 'headerPattern' => '//',
803 'custom_field_id' => $this->getCustomFieldID('state'),
804 'groupTitle' => 'Custom Group',
805 'default_value' => NULL,
806 'custom_group_id' => $customGroupID,
807 'extends' => 'Contact',
808 'extends_entity_column_value' => NULL,
809 'extends_entity_column_id' => NULL,
811 'is_multiple' => '0',
812 'option_group_id' => NULL,
813 'date_format' => NULL,
814 'time_format' => NULL,
816 'table_name' => 'civicrm_value_custom_group_' . $customGroupID,
817 'column_name' => $this->getCustomFieldColumnName('state'),
818 'where' => 'civicrm_value_custom_group_' . $customGroupID . '.' . $this->getCustomFieldColumnName('state'),
819 'extends_table' => 'civicrm_contact',
820 'search_table' => 'contact_a',
822 'pseudoconstant' => [
823 'table' => 'civicrm_state_province',
825 'labelColumn' => 'name',
828 'data_type' => 'StateProvince',
830 'html_type' => 'Select',
831 'text_length' => NULL,
832 'options_per_line' => NULL,
833 'is_search_range' => '0',
835 $this->getCustomFieldName('multi_state') => [
836 'id' => $this->getCustomFieldID('multi_state'),
837 'label' => 'State-multi',
838 'headerPattern' => '//',
839 'title' => 'State-multi',
840 'custom_field_id' => $this->getCustomFieldID('multi_state'),
841 'groupTitle' => 'Custom Group',
842 'default_value' => NULL,
843 'custom_group_id' => $customGroupID,
844 'extends' => 'Contact',
845 'extends_entity_column_value' => NULL,
846 'extends_entity_column_id' => NULL,
848 'is_multiple' => '0',
849 'option_group_id' => NULL,
850 'date_format' => NULL,
851 'time_format' => NULL,
853 'table_name' => 'civicrm_value_custom_group_' . $customGroupID,
854 'column_name' => $this->getCustomFieldColumnName('multi_state'),
855 'where' => 'civicrm_value_custom_group_' . $customGroupID . '.' . $this->getCustomFieldColumnName('multi_state'),
856 'extends_table' => 'civicrm_contact',
857 'search_table' => 'contact_a',
859 'pseudoconstant' => [
860 'table' => 'civicrm_state_province',
862 'labelColumn' => 'name',
865 'data_type' => 'StateProvince',
866 'name' => $this->getCustomFieldName('multi_state'),
868 'html_type' => 'Select',
869 'text_length' => NULL,
870 'options_per_line' => NULL,
871 'is_search_range' => '0',
873 $this->getCustomFieldName('boolean') => [
874 'id' => $this->getCustomFieldID('boolean'),
876 'headerPattern' => '//',
878 'custom_field_id' => $this->getCustomFieldID('boolean'),
879 'groupTitle' => 'Custom Group',
880 'default_value' => NULL,
881 'custom_group_id' => $customGroupID,
882 'extends' => 'Contact',
883 'extends_entity_column_value' => NULL,
884 'extends_entity_column_id' => NULL,
886 'is_multiple' => '0',
887 'option_group_id' => NULL,
888 'date_format' => NULL,
889 'time_format' => NULL,
891 'table_name' => 'civicrm_value_custom_group_' . $customGroupID,
892 'column_name' => $this->getCustomFieldColumnName('boolean'),
893 'where' => 'civicrm_value_custom_group_' . $customGroupID . '.' . $this->getCustomFieldColumnName('boolean'),
894 'extends_table' => 'civicrm_contact',
895 'search_table' => 'contact_a',
897 'data_type' => 'Boolean',
898 'name' => $this->getCustomFieldName('boolean'),
900 'html_type' => 'Radio',
901 'text_length' => NULL,
902 'options_per_line' => NULL,
903 'is_search_range' => '0',
905 'pseudoconstant' => [
906 'callback' => 'CRM_Core_SelectValues::boolean',
909 $this->getCustomFieldName('checkbox') => [
910 'name' => $this->getCustomFieldName('checkbox'),
911 'custom_field_id' => $this->getCustomFieldID('checkbox'),
912 'id' => $this->getCustomFieldID('checkbox'),
913 'groupTitle' => 'Custom Group',
914 'default_value' => NULL,
915 'option_group_id' => $this->getOptionGroupID('checkbox'),
916 'custom_group_id' => $customGroupID,
917 'extends' => 'Contact',
918 'extends_entity_column_value' => NULL,
919 'extends_entity_column_id' => NULL,
921 'is_multiple' => '0',
922 'date_format' => NULL,
923 'time_format' => NULL,
925 'table_name' => 'civicrm_value_custom_group_' . $customGroupID,
926 'column_name' => $this->getCustomFieldColumnName('checkbox'),
927 'where' => 'civicrm_value_custom_group_' . $customGroupID . '.' . $this->getCustomFieldColumnName('checkbox'),
928 'extends_table' => 'civicrm_contact',
929 'search_table' => 'contact_a',
931 'label' => 'Pick Shade',
932 'headerPattern' => '//',
933 'title' => 'Pick Shade',
934 'data_type' => 'String',
936 'html_type' => 'CheckBox',
937 'text_length' => NULL,
938 'options_per_line' => NULL,
939 'is_search_range' => '0',
941 'pseudoconstant' => [
942 'optionGroupName' => $this->getOptionGroupName('checkbox'),
943 'optionEditPath' => 'civicrm/admin/options/' . $this->getOptionGroupName('checkbox'),
948 $this->assertEquals($expected, CRM_Core_BAO_CustomField
::getFieldsForImport());
952 * Test the bulk create function works.
954 public function testBulkCreate(): void
{
955 $customGroup = $this->customGroupCreate([
956 'extends' => 'Individual',
957 'title' => 'my bulk group',
959 CustomField
::save(FALSE)->setRecords([
962 'data_type' => 'String',
963 'html_type' => 'Text',
964 'column_name' => 'my_text',
967 'label' => 'test_link',
968 'data_type' => 'Link',
969 'html_type' => 'Link',
970 'is_search_range' => '0',
974 'custom_group_id' => $customGroup['id'],
976 'is_searchable' => 1,
978 $dao = CRM_Core_DAO
::executeQuery(('SHOW CREATE TABLE ' . $customGroup['values'][$customGroup['id']]['table_name']));
980 $this->assertStringContainsString('`test_link_2` varchar(255) COLLATE ' . CRM_Core_BAO_SchemaHandler
::getInUseCollation() . ' DEFAULT NULL', $dao->Create_Table
);
981 $this->assertStringContainsString('KEY `INDEX_my_text` (`my_text`)', $dao->Create_Table
);
985 * Check that outputting the display value for a file field with No description doesn't generate error
987 public function testFileDisplayValueNoDescription() {
988 $customGroup = $this->customGroupCreate([
989 'extends' => 'Individual',
990 'title' => 'Test Contact File Custom Group',
992 $fileField = $this->customFieldCreate([
993 'custom_group_id' => $customGroup['id'],
994 'data_type' => 'File',
995 'html_type' => 'File',
996 'default_value' => '',
998 $filePath = Civi
::paths()->getPath('[civicrm.files]/custom/test_file.txt');
999 $file = $this->callAPISuccess('File', 'create', [
1002 $individual = $this->individualCreate(['custom_' . $fileField['id'] => $file['id']]);
1003 $expectedDisplayValue = CRM_Core_BAO_File
::paperIconAttachment('*', $file['id'])[$file['id']];
1004 $this->assertEquals($expectedDisplayValue, CRM_Core_BAO_CustomField
::displayValue($file['id'], $fileField['id']));
1008 * Test for hook_civicrm_alterCustomFieldDisplayValue().
1010 public function testAlterCustomFieldDisplayValueHook() {
1011 CRM_Utils_Hook_UnitTests
::singleton()->setHook('civicrm_alterCustomFieldDisplayValue', [$this, 'alterCustomFieldDisplayValue']);
1012 $customGroupId = $this->customGroupCreate([
1013 'extends' => 'Individual',
1014 'title' => 'Test Contactcustom Group',
1016 $fieldId = $this->customFieldCreate([
1017 'custom_group_id' => $customGroupId,
1018 'name' => 'alter_cf_field',
1019 'label' => 'Alter CF Field',
1021 $contactId = $this->individualCreate(['custom_' . $fieldId => 'Test']);
1023 $this->assertEquals('Test', $this->callAPISuccessGetValue('Contact',
1024 ['id' => $contactId, 'return' => "custom_{$fieldId}"]
1029 'custom_' . $fieldId => $this->callAPISuccess('Contact', 'getfield', [
1030 'name' => 'custom_' . $fieldId,
1035 // CRM_Core_BAO_UFGroup::getValues() invokes CRM_Core_BAO_CustomField::displayValue() function.
1036 CRM_Core_BAO_UFGroup
::getValues($contactId, $fields, $values);
1037 $this->assertEquals('New value', $values['Alter CF Field']);
1041 * @param string $displayValue
1042 * @param mixed $value
1043 * @param int $entityId
1044 * @param array $fieldInfo
1047 public function alterCustomFieldDisplayValue(&$displayValue, $value, $entityId, $fieldInfo) {
1048 if ($fieldInfo['name'] == 'alter_cf_field') {
1049 $displayValue = 'New value';
1054 * Test for single select Autocomplete custom field.
1057 public function testSingleSelectAutoComplete() {
1058 $customGroupId = $this->customGroupCreate([
1059 'extends' => 'Individual',
1061 $colors = ['Y' => 'Yellow', 'G' => 'Green'];
1062 $fieldId = $this->createAutoCompleteCustomField([
1063 'custom_group_id' => $customGroupId,
1064 'option_values' => $colors,
1066 $contactId = $this->individualCreate(['custom_' . $fieldId => 'Y']);
1067 $value = $this->callAPISuccessGetValue('Contact', [
1069 'return' => 'custom_' . $fieldId,
1071 $this->assertEquals('Y', $value);
1075 * Test for multi select Autocomplete custom field.
1078 public function testMultiSelectAutoComplete() {
1079 $customGroupId = $this->customGroupCreate([
1080 'extends' => 'Individual',
1082 $colors = ['Y' => 'Yellow', 'G' => 'Green'];
1083 $fieldId = $this->createAutoCompleteCustomField([
1084 'custom_group_id' => $customGroupId,
1086 'option_values' => $colors,
1088 $contactId = $this->individualCreate(['custom_' . $fieldId => ['Y', 'G']]);
1089 $value = $this->callAPISuccessGetValue('Contact', [
1091 'return' => 'custom_' . $fieldId,
1093 $this->assertEquals(array_keys($colors), $value);