Merge pull request #17253 from mattwire/utf8convertblocksize
[civicrm-core.git] / tests / phpunit / CRM / Core / FieldOptionsTest.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 * Tests for field options
14 * @group headless
15 */
16 class CRM_Core_FieldOptionsTest extends CiviUnitTestCase {
17
18 /**
19 * @var array
20 */
21 public $replaceOptions;
22
23 /**
24 * @var array
25 */
26 public $appendOptions;
27
28 /**
29 * @var string
30 */
31 public $targetField;
32
33 public function setUp() {
34 parent::setUp();
35 CRM_Utils_Hook::singleton()->setHook('civicrm_fieldOptions', [$this, 'hook_civicrm_fieldOptions']);
36 }
37
38 public function tearDown() {
39 parent::tearDown();
40 $this->quickCleanup(['civicrm_custom_field', 'civicrm_custom_group']);
41 }
42
43 /**
44 * Assure CRM_Core_PseudoConstant::get() is working properly for a range of
45 * DAO fields having a <pseudoconstant> tag in the XML schema.
46 */
47 public function testOptionValues() {
48 /**
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.
58 */
59 $fields = [
60 'CRM_Core_BAO_Address' => [
61 [
62 'fieldName' => 'state_province_id',
63 'sample' => 'California',
64 'max' => 60,
65 'props' => ['country_id' => 1228],
66 ],
67 ],
68 'CRM_Contact_BAO_Contact' => [
69 [
70 'fieldName' => 'contact_sub_type',
71 'sample' => 'Team',
72 'exclude' => 'Organization',
73 'props' => ['contact_type' => 'Organization'],
74 ],
75 ],
76 ];
77
78 foreach ($fields as $baoName => $baoFields) {
79 foreach ($baoFields as $field) {
80 $message = "BAO name: '{$baoName}', field: '{$field['fieldName']}'";
81
82 $props = CRM_Utils_Array::value('props', $field, []);
83 $optionValues = $baoName::buildOptions($field['fieldName'], 'create', $props);
84 $this->assertNotEmpty($optionValues, $message);
85
86 // Ensure sample value is contained in the returned optionValues.
87 $this->assertContains($field['sample'], $optionValues, $message);
88
89 // Exclude test
90 if (!empty($field['exclude'])) {
91 $this->assertNotContains($field['exclude'], $optionValues, $message);
92 }
93
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);
97 }
98 }
99 }
100
101 /**
102 * Ensure hook_civicrm_fieldOptions is working
103 */
104 public function testHookFieldOptions() {
105 CRM_Core_PseudoConstant::flush();
106
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);
112
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);
116
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);
124 }
125
126 /**
127 * Ensure hook_civicrm_fieldOptions works with custom fields
128 */
129 public function testHookFieldOptionsWithCustomFields() {
130 // Create a custom field group for testing.
131 $custom_group_name = md5(microtime());
132 $api_params = [
133 'title' => $custom_group_name,
134 'extends' => 'Individual',
135 'is_active' => TRUE,
136 ];
137 $customGroup = $this->callAPISuccess('customGroup', 'create', $api_params);
138
139 // Add a custom select field.
140 $api_params = [
141 'custom_group_id' => $customGroup['id'],
142 'label' => $custom_group_name . 1,
143 'html_type' => 'Select',
144 'data_type' => 'String',
145 'option_values' => [
146 'foo' => 'Foo',
147 'bar' => 'Bar',
148 ],
149 ];
150 $result = $this->callAPISuccess('custom_field', 'create', $api_params);
151 $customField1 = $result['id'];
152
153 // Add a custom country field.
154 $api_params = [
155 'custom_group_id' => $customGroup['id'],
156 'label' => $custom_group_name . 2,
157 'html_type' => 'Select Country',
158 'data_type' => 'Country',
159 ];
160 $result = $this->callAPISuccess('custom_field', 'create', $api_params);
161 $customField2 = $result['id'];
162
163 // Add a custom boolean field.
164 $api_params = [
165 'custom_group_id' => $customGroup['id'],
166 'label' => $custom_group_name . 3,
167 'html_type' => 'Radio',
168 'data_type' => 'Boolean',
169 ];
170 $result = $this->callAPISuccess('custom_field', 'create', $api_params);
171 $customField3 = $result['id'];
172
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());
179
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());
185
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);
191 }
192
193 /**
194 * Implements hook_civicrm_fieldOptions().
195 */
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;
200 }
201 if ($this->appendOptions) {
202 $options += $this->appendOptions;
203 }
204 }
205 }
206
207 }