Merge pull request #12053 from civicrm/5.1
[civicrm-core.git] / tests / phpunit / CRM / Core / FieldOptionsTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2018 |
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 +--------------------------------------------------------------------+
26 */
27
28 /**
29 * Tests for field options
30 * @group headless
31 */
32 class CRM_Core_FieldOptionsTest extends CiviUnitTestCase {
33
34 /**
35 * @var array
36 */
37 public $replaceOptions;
38
39 /**
40 * @var array
41 */
42 public $appendOptions;
43
44 /**
45 * @var string
46 */
47 public $targetField;
48
49 public function setUp() {
50 parent::setUp();
51 CRM_Utils_Hook::singleton()->setHook('civicrm_fieldOptions', array($this, 'hook_civicrm_fieldOptions'));
52 }
53
54 public function tearDown() {
55 parent::tearDown();
56 $this->quickCleanup(array('civicrm_custom_field', 'civicrm_custom_group'));
57 }
58
59 /**
60 * Assure CRM_Core_PseudoConstant::get() is working properly for a range of
61 * DAO fields having a <pseudoconstant> tag in the XML schema.
62 */
63 public function testOptionValues() {
64 /**
65 * baoName/field combinations to test
66 * Format: array[BAO Name] = $properties, where properties is an array whose
67 * named members can be:
68 * - fieldName: the SQL column name within the DAO table.
69 * - sample: Any one value which is expected in the list of option values.
70 * - context: Context to pass
71 * - props: Object properties to pass
72 * - exclude: Any one value which should not be in the list.
73 * - max: integer (default = 10) maximum number of option values expected.
74 */
75 $fields = array(
76 'CRM_Core_BAO_Address' => array(
77 array(
78 'fieldName' => 'state_province_id',
79 'sample' => 'California',
80 'max' => 60,
81 'props' => array('country_id' => 1228),
82 ),
83 ),
84 'CRM_Contact_BAO_Contact' => array(
85 array(
86 'fieldName' => 'contact_sub_type',
87 'sample' => 'Team',
88 'exclude' => 'Organization',
89 'props' => array('contact_type' => 'Organization'),
90 ),
91 ),
92 );
93
94 foreach ($fields as $baoName => $baoFields) {
95 foreach ($baoFields as $field) {
96 $message = "BAO name: '{$baoName}', field: '{$field['fieldName']}'";
97
98 $props = CRM_Utils_Array::value('props', $field, array());
99 $optionValues = $baoName::buildOptions($field['fieldName'], 'create', $props);
100 $this->assertNotEmpty($optionValues, $message);
101
102 // Ensure sample value is contained in the returned optionValues.
103 $this->assertContains($field['sample'], $optionValues, $message);
104
105 // Exclude test
106 if (!empty($field['exclude'])) {
107 $this->assertNotContains($field['exclude'], $optionValues, $message);
108 }
109
110 // Ensure count of optionValues is not extraordinarily high.
111 $max = CRM_Utils_Array::value('max', $field, 10);
112 $this->assertLessThanOrEqual($max, count($optionValues), $message);
113 }
114 }
115 }
116
117 /**
118 * Ensure hook_civicrm_fieldOptions is working
119 */
120 public function testHookFieldOptions() {
121 CRM_Core_PseudoConstant::flush();
122
123 // Test replacing all options with a hook
124 $this->targetField = 'case_type_id';
125 $this->replaceOptions = array('foo' => 'Foo', 'bar' => 'Bar');
126 $result = $this->callAPISuccess('case', 'getoptions', array('field' => 'case_type_id'));
127 $this->assertEquals($result['values'], $this->replaceOptions);
128
129 // TargetField doesn't match - should get unmodified option list
130 $originalGender = CRM_Contact_BAO_Contact::buildOptions('gender_id');
131 $this->assertNotEquals($originalGender, $this->replaceOptions);
132
133 // This time we should get foo bar appended to the list
134 $this->targetField = 'gender_id';
135 $this->appendOptions = array('foo' => 'Foo', 'bar' => 'Bar');
136 $this->replaceOptions = NULL;
137 CRM_Core_PseudoConstant::flush();
138 $result = CRM_Contact_BAO_Contact::buildOptions('gender_id');
139 $this->assertEquals($result, $originalGender + $this->appendOptions);
140 }
141
142 /**
143 * Ensure hook_civicrm_fieldOptions works with custom fields
144 */
145 public function testHookFieldOptionsWithCustomFields() {
146 // Create a custom field group for testing.
147 $custom_group_name = md5(microtime());
148 $api_params = array(
149 'title' => $custom_group_name,
150 'extends' => 'Individual',
151 'is_active' => TRUE,
152 );
153 $customGroup = $this->callAPISuccess('customGroup', 'create', $api_params);
154
155 // Add a custom select field.
156 $api_params = array(
157 'custom_group_id' => $customGroup['id'],
158 'label' => $custom_group_name . 1,
159 'html_type' => 'Select',
160 'data_type' => 'String',
161 'option_values' => array(
162 'foo' => 'Foo',
163 'bar' => 'Bar',
164 ),
165 );
166 $result = $this->callAPISuccess('custom_field', 'create', $api_params);
167 $customField1 = $result['id'];
168
169 // Add a custom country field.
170 $api_params = array(
171 'custom_group_id' => $customGroup['id'],
172 'label' => $custom_group_name . 2,
173 'html_type' => 'Select Country',
174 'data_type' => 'Country',
175 );
176 $result = $this->callAPISuccess('custom_field', 'create', $api_params);
177 $customField2 = $result['id'];
178
179 // Add a custom boolean field.
180 $api_params = array(
181 'custom_group_id' => $customGroup['id'],
182 'label' => $custom_group_name . 3,
183 'html_type' => 'Radio',
184 'data_type' => 'Boolean',
185 );
186 $result = $this->callAPISuccess('custom_field', 'create', $api_params);
187 $customField3 = $result['id'];
188
189 $this->targetField = 'custom_' . $customField1;
190 $this->replaceOptions = NULL;
191 $this->appendOptions = array('baz' => 'Baz');
192 $field = new CRM_Core_BAO_CustomField();
193 $field->id = $customField1;
194 $this->assertEquals(array('foo' => 'Foo', 'bar' => 'Bar', 'baz' => 'Baz'), $field->getOptions());
195
196 $this->targetField = 'custom_' . $customField2;
197 $this->replaceOptions = array('nowhere' => 'Nowhere');
198 $field = new CRM_Core_BAO_CustomField();
199 $field->id = $customField2;
200 $this->assertEquals($this->replaceOptions + $this->appendOptions, $field->getOptions());
201
202 $this->targetField = 'custom_' . $customField3;
203 $this->replaceOptions = NULL;
204 $this->appendOptions = array(2 => 'Maybe');
205 $options = CRM_Core_PseudoConstant::get('CRM_Core_BAO_CustomField', $this->targetField);
206 $this->assertEquals(array(1 => 'Yes', 0 => 'No', 2 => 'Maybe'), $options);
207
208 $field->free();
209 }
210
211 /**
212 * Implements hook_civicrm_fieldOptions().
213 */
214 public function hook_civicrm_fieldOptions($entity, $field, &$options, $params) {
215 if ($field == $this->targetField) {
216 if (is_array($this->replaceOptions)) {
217 $options = $this->replaceOptions;
218 }
219 if ($this->appendOptions) {
220 $options += $this->appendOptions;
221 }
222 }
223 }
224
225 }