3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
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 +--------------------------------------------------------------------+
13 * Tests for field options
16 class CRM_Core_FieldOptionsTest
extends CiviUnitTestCase
{
21 public $replaceOptions;
26 public $appendOptions;
33 public function setUp() {
35 CRM_Utils_Hook
::singleton()->setHook('civicrm_fieldOptions', [$this, 'hook_civicrm_fieldOptions']);
38 public function tearDown() {
40 $this->quickCleanup(['civicrm_custom_field', 'civicrm_custom_group']);
44 * Assure CRM_Core_PseudoConstant::get() is working properly for a range of
45 * DAO fields having a <pseudoconstant> tag in the XML schema.
47 public function testOptionValues() {
49 * baoName/field combinations to test
50 * Format: array[BAO Name] = $properties, where properties is an array whose
51 * named members can be:
52 * - fieldName: the SQL column name within the DAO table.
53 * - sample: Any one value which is expected in the list of option values.
54 * - context: Context to pass
55 * - props: Object properties to pass
56 * - exclude: Any one value which should not be in the list.
57 * - max: integer (default = 10) maximum number of option values expected.
60 'CRM_Core_BAO_Address' => [
62 'fieldName' => 'state_province_id',
63 'sample' => 'California',
65 'props' => ['country_id' => 1228],
68 'CRM_Contact_BAO_Contact' => [
70 'fieldName' => 'contact_sub_type',
72 'exclude' => 'Organization',
73 'props' => ['contact_type' => 'Organization'],
78 foreach ($fields as $baoName => $baoFields) {
79 foreach ($baoFields as $field) {
80 $message = "BAO name: '{$baoName}', field: '{$field['fieldName']}'";
82 $props = CRM_Utils_Array
::value('props', $field, []);
83 $optionValues = $baoName::buildOptions($field['fieldName'], 'create', $props);
84 $this->assertNotEmpty($optionValues, $message);
86 // Ensure sample value is contained in the returned optionValues.
87 $this->assertContains($field['sample'], $optionValues, $message);
90 if (!empty($field['exclude'])) {
91 $this->assertNotContains($field['exclude'], $optionValues, $message);
94 // Ensure count of optionValues is not extraordinarily high.
95 $max = CRM_Utils_Array
::value('max', $field, 10);
96 $this->assertLessThanOrEqual($max, count($optionValues), $message);
102 * Ensure hook_civicrm_fieldOptions is working
104 public function testHookFieldOptions() {
105 CRM_Core_PseudoConstant
::flush();
107 // Test replacing all options with a hook
108 $this->targetField
= 'case_type_id';
109 $this->replaceOptions
= ['foo' => 'Foo', 'bar' => 'Bar'];
110 $result = $this->callAPISuccess('case', 'getoptions', ['field' => 'case_type_id']);
111 $this->assertEquals($result['values'], $this->replaceOptions
);
113 // TargetField doesn't match - should get unmodified option list
114 $originalGender = CRM_Contact_BAO_Contact
::buildOptions('gender_id');
115 $this->assertNotEquals($originalGender, $this->replaceOptions
);
117 // This time we should get foo bar appended to the list
118 $this->targetField
= 'gender_id';
119 $this->appendOptions
= ['foo' => 'Foo', 'bar' => 'Bar'];
120 $this->replaceOptions
= NULL;
121 CRM_Core_PseudoConstant
::flush();
122 $result = CRM_Contact_BAO_Contact
::buildOptions('gender_id');
123 $this->assertEquals($result, $originalGender +
$this->appendOptions
);
127 * Ensure hook_civicrm_fieldOptions works with custom fields
129 public function testHookFieldOptionsWithCustomFields() {
130 // Create a custom field group for testing.
131 $custom_group_name = md5(microtime());
133 'title' => $custom_group_name,
134 'extends' => 'Individual',
137 $customGroup = $this->callAPISuccess('customGroup', 'create', $api_params);
139 // Add a custom select field.
141 'custom_group_id' => $customGroup['id'],
142 'label' => $custom_group_name . 1,
143 'html_type' => 'Select',
144 'data_type' => 'String',
150 $result = $this->callAPISuccess('custom_field', 'create', $api_params);
151 $customField1 = $result['id'];
153 // Add a custom country field.
155 'custom_group_id' => $customGroup['id'],
156 'label' => $custom_group_name . 2,
157 'html_type' => 'Select Country',
158 'data_type' => 'Country',
160 $result = $this->callAPISuccess('custom_field', 'create', $api_params);
161 $customField2 = $result['id'];
163 // Add a custom boolean field.
165 'custom_group_id' => $customGroup['id'],
166 'label' => $custom_group_name . 3,
167 'html_type' => 'Radio',
168 'data_type' => 'Boolean',
170 $result = $this->callAPISuccess('custom_field', 'create', $api_params);
171 $customField3 = $result['id'];
173 $this->targetField
= 'custom_' . $customField1;
174 $this->replaceOptions
= NULL;
175 $this->appendOptions
= ['baz' => 'Baz'];
176 $field = new CRM_Core_BAO_CustomField();
177 $field->id
= $customField1;
178 $this->assertEquals(['foo' => 'Foo', 'bar' => 'Bar', 'baz' => 'Baz'], $field->getOptions());
180 $this->targetField
= 'custom_' . $customField2;
181 $this->replaceOptions
= ['nowhere' => 'Nowhere'];
182 $field = new CRM_Core_BAO_CustomField();
183 $field->id
= $customField2;
184 $this->assertEquals($this->replaceOptions +
$this->appendOptions
, $field->getOptions());
186 $this->targetField
= 'custom_' . $customField3;
187 $this->replaceOptions
= NULL;
188 $this->appendOptions
= [2 => 'Maybe'];
189 $options = CRM_Core_PseudoConstant
::get('CRM_Core_BAO_CustomField', $this->targetField
);
190 $this->assertEquals([1 => 'Yes', 0 => 'No', 2 => 'Maybe'], $options);
194 * Implements hook_civicrm_fieldOptions().
196 public function hook_civicrm_fieldOptions($entity, $field, &$options, $params) {
197 if ($field == $this->targetField
) {
198 if (is_array($this->replaceOptions
)) {
199 $options = $this->replaceOptions
;
201 if ($this->appendOptions
) {
202 $options +
= $this->appendOptions
;