Commit | Line | Data |
---|---|---|
6a488035 | 1 | <?php |
7d61e75f TO |
2 | |
3 | /* | |
4 | +--------------------------------------------------------------------+ | |
5 | | Copyright CiviCRM LLC. All rights reserved. | | |
6 | | | | |
7 | | This work is published under the GNU AGPLv3 license with some | | |
8 | | permitted exceptions and without any warranty. For full license | | |
9 | | and copyright information, see https://civicrm.org/licensing | | |
10 | +--------------------------------------------------------------------+ | |
6c6e6187 | 11 | */ |
6a488035 | 12 | |
e9479dcf EM |
13 | /** |
14 | * Class api_v3_CustomValueTest | |
acb109b7 | 15 | * @group headless |
e9479dcf | 16 | */ |
6a488035 | 17 | class api_v3_CustomValueTest extends CiviUnitTestCase { |
6c6e6187 | 18 | protected $_apiversion = 3; |
f9a5aadd | 19 | |
ec28b24d | 20 | protected $optionGroup; |
b7c9bc4c | 21 | |
6a488035 TO |
22 | public $DBResetRequired = FALSE; |
23 | ||
56fbe1df YN |
24 | /** |
25 | * @throws \CRM_Core_Exception | |
26 | */ | |
6fca1a34 | 27 | public function _populateOptionAndCustomGroup($type = NULL) { |
9099cab3 CW |
28 | $dataValues = [ |
29 | 'integer' => [1, 2, 3], | |
30 | 'number' => [10.11, 20.22, 30.33], | |
31 | 'string' => [substr(sha1(rand()), 0, 4) . '(', substr(sha1(rand()), 0, 3) . '|', substr(sha1(rand()), 0, 2) . ','], | |
f9887f64 | 32 | // 'country' => array_rand(CRM_Core_PseudoConstant::country(FALSE, FALSE), 3), |
33 | // This does not work in the test at the moment due to caching issues. | |
34 | //'state_province' => array_rand(CRM_Core_PseudoConstant::stateProvince(FALSE, FALSE), 3), | |
ec28b24d | 35 | 'date' => NULL, |
a6d226f4 | 36 | 'contact' => NULL, |
872a35c1 | 37 | 'boolean' => NULL, |
9099cab3 | 38 | ]; |
ec28b24d | 39 | |
9099cab3 | 40 | $dataValues = !empty($type) ? [$type => $dataValues[$type]] : $dataValues; |
6fca1a34 | 41 | |
ec28b24d | 42 | foreach ($dataValues as $dataType => $values) { |
9099cab3 | 43 | $this->optionGroup[$dataType] = ['values' => $values]; |
ec28b24d | 44 | if (!empty($values)) { |
ec28b24d | 45 | $result = $this->callAPISuccess('OptionGroup', 'create', |
9099cab3 | 46 | [ |
ec28b24d | 47 | 'name' => "{$dataType}_group", |
9099cab3 CW |
48 | 'api.option_value.create' => ['label' => "$dataType 1", 'value' => $values[0]], |
49 | 'api.option_value.create.1' => ['label' => "$dataType 2", 'value' => $values[1]], | |
50 | 'api.option_value.create.2' => ['label' => "$dataType 3", 'value' => $values[2]], | |
51 | ] | |
ec28b24d | 52 | ); |
53 | $this->optionGroup[$dataType]['id'] = $result['id']; | |
54 | } | |
56fbe1df | 55 | elseif ($dataType === 'contact') { |
f819588f | 56 | for ($i = 0; $i < 3; $i++) { |
9099cab3 | 57 | $result = $this->callAPISuccess('Contact', 'create', ['contact_type' => 'Individual', 'email' => substr(sha1(rand()), 0, 7) . '@yahoo.com']); |
a6d226f4 | 58 | $this->optionGroup[$dataType]['values'][$i] = $result['id']; |
59 | } | |
60 | } | |
ec28b24d | 61 | $this->ids[$dataType] = $this->entityCustomGroupWithSingleFieldCreate("$dataType Custom Group", 'Contacts'); |
62 | } | |
63 | ||
6a488035 TO |
64 | } |
65 | ||
11ba3ace | 66 | public function tearDown(): void { |
9099cab3 | 67 | $tablesToTruncate = [ |
6a488035 TO |
68 | 'civicrm_email', |
69 | 'civicrm_custom_field', | |
70 | 'civicrm_custom_group', | |
71 | 'civicrm_contact', | |
9099cab3 | 72 | ]; |
6a488035 TO |
73 | |
74 | // true tells quickCleanup to drop any tables that might have been created in the test | |
75 | $this->quickCleanup($tablesToTruncate, TRUE); | |
6fca1a34 | 76 | |
77 | // cleanup created option group for each custom-set before running next test | |
78 | if (!empty($this->optionGroup)) { | |
56fbe1df | 79 | foreach ($this->optionGroup as $value) { |
6fca1a34 | 80 | if (!empty($value['id'])) { |
9099cab3 | 81 | $count = $this->callAPISuccess('OptionGroup', 'get', ['id' => $value['id']]); |
a60c0bc8 | 82 | if ((bool) $count['count']) { |
9099cab3 | 83 | $this->callAPISuccess('OptionGroup', 'delete', ['id' => $value['id']]); |
a60c0bc8 | 84 | } |
6fca1a34 | 85 | } |
86 | } | |
87 | } | |
56fbe1df | 88 | parent::tearDown(); |
6a488035 TO |
89 | } |
90 | ||
91 | public function testCreateCustomValue() { | |
6fca1a34 | 92 | $this->_populateOptionAndCustomGroup(); |
9099cab3 | 93 | $this->_customField = $this->customFieldCreate(['custom_group_id' => $this->ids['string']['custom_group_id']]); |
0ec36ef1 | 94 | $this->_customFieldID = $this->_customField['id']; |
6fca1a34 | 95 | |
c44d3d25 | 96 | $customFieldDataType = array_column(CRM_Core_BAO_CustomField::dataType(), 'id'); |
5d2f1ed6 | 97 | $dataToHtmlTypes = CRM_Custom_Form_Field::$_dataToHTML; |
9b85cd33 | 98 | $optionSupportingHTMLTypes = CRM_Custom_Form_Field::$htmlTypesWithOptions; |
6a488035 | 99 | |
c44d3d25 | 100 | foreach ($customFieldDataType as $dataType) { |
ec28b24d | 101 | switch ($dataType) { |
9b85cd33 | 102 | // skipping File data-type & state province due to caching issues |
f9887f64 | 103 | // case 'Country': |
104 | // case 'StateProvince': | |
ec28b24d | 105 | case 'String': |
106 | case 'Link': | |
107 | case 'Int': | |
108 | case 'Float': | |
109 | case 'Money': | |
872a35c1 | 110 | case 'Date': |
872a35c1 | 111 | case 'Boolean': |
112 | ||
113 | //Based on the custom field data-type choose desired SQL operators(to test with) and basic $type | |
9099cab3 CW |
114 | if (in_array($dataType, ['String', 'Link'])) { |
115 | $validSQLOperators = ['=', '!=', 'IN', 'NOT IN', 'LIKE', 'NOT LIKE', 'IS NOT NULL', 'IS NULL']; | |
ec28b24d | 116 | $type = 'string'; |
117 | } | |
872a35c1 | 118 | elseif ($dataType == 'Boolean') { |
9099cab3 | 119 | $validSQLOperators = ['=', '!=', 'IS NOT NULL', 'IS NULL']; |
872a35c1 | 120 | $type = 'boolean'; |
121 | } | |
ec28b24d | 122 | else { |
872a35c1 | 123 | if ($dataType == 'Country') { |
124 | $type = 'country'; | |
125 | } | |
126 | elseif ($dataType == 'StateProvince') { | |
ec28b24d | 127 | $type = 'state_province'; |
128 | } | |
a6d226f4 | 129 | elseif ($dataType == 'ContactReference') { |
130 | $type = 'contact'; | |
131 | } | |
132 | elseif ($dataType == 'Date') { | |
133 | $type = 'date'; | |
134 | } | |
ec28b24d | 135 | else { |
a6d226f4 | 136 | $type = $dataType == 'Int' ? 'integer' : 'number'; |
ec28b24d | 137 | } |
9099cab3 | 138 | $validSQLOperators = ['=', '!=', 'IN', 'NOT IN', '<=', '>=', '>', '<', 'IS NOT NULL', 'IS NULL']; |
ec28b24d | 139 | } |
6a488035 | 140 | |
872a35c1 | 141 | //Create custom field of $dataType and html-type $html |
9b85cd33 | 142 | foreach ($dataToHtmlTypes[$dataType] as $html) { |
f9887f64 | 143 | // per CRM-18568 the like operator does not currently work for fields with options. |
144 | // the LIKE operator could potentially bypass ACLs (as could IS NOT NULL) and some thought needs to be given | |
145 | // to it. | |
146 | if (in_array($html, $optionSupportingHTMLTypes)) { | |
9099cab3 | 147 | $validSQLOperators = array_diff($validSQLOperators, ['LIKE', 'NOT LIKE']); |
f9887f64 | 148 | } |
9099cab3 | 149 | $params = [ |
ec28b24d | 150 | 'custom_group_id' => $this->ids[$type]['custom_group_id'], |
151 | 'label' => "$dataType - $html", | |
152 | 'data_type' => $dataType, | |
153 | 'html_type' => $html, | |
154 | 'default_value' => NULL, | |
9099cab3 CW |
155 | ]; |
156 | if (!in_array($html, ['Text', 'TextArea']) && !in_array($dataType, ['Link', 'Date', 'ContactReference', 'Boolean'])) { | |
157 | $params += ['option_group_id' => $this->optionGroup[$type]['id']]; | |
ec28b24d | 158 | } |
159 | $customField = $this->customFieldCreate($params); | |
872a35c1 | 160 | //Now test with $validSQLOperator SQL operators against its custom value(s) |
161 | $this->_testCustomValue($customField['values'][$customField['id']], $validSQLOperators, $type); | |
ec28b24d | 162 | } |
6a488035 | 163 | |
ec28b24d | 164 | } |
165 | } | |
166 | } | |
6a488035 | 167 | |
ec28b24d | 168 | public function _testCustomValue($customField, $sqlOps, $type) { |
169 | $isSerialized = CRM_Core_BAO_CustomField::isSerialized($customField); | |
170 | $customId = $customField['id']; | |
9099cab3 | 171 | $params = [ |
6a488035 | 172 | 'contact_type' => 'Individual', |
ec28b24d | 173 | 'email' => substr(sha1(rand()), 0, 7) . 'man1@yahoo.com', |
9099cab3 | 174 | ]; |
fc928539 | 175 | $result = $this->callAPISuccess('Contact', 'create', $params); |
ec28b24d | 176 | $contactId = $result['id']; |
6a488035 | 177 | |
8007b543 | 178 | $count = rand(1, 2); |
f9887f64 | 179 | |
ec28b24d | 180 | if ($isSerialized) { |
181 | $selectedValue = $this->optionGroup[$type]['values']; | |
182 | $notselectedValue = $selectedValue[$count]; | |
183 | unset($selectedValue[$count]); | |
184 | } | |
185 | elseif ($customField['html_type'] == 'Link') { | |
186 | $selectedValue = "http://" . substr(sha1(rand()), 0, 7) . ".com"; | |
187 | $notselectedValue = "http://" . substr(sha1(rand()), 0, 7) . ".com"; | |
188 | } | |
189 | elseif ($type == 'date') { | |
190 | $selectedValue = date('Ymd'); | |
a6d226f4 | 191 | $notselectedValue = $lesserSelectedValue = date('Ymd', strtotime('yesterday')); |
192 | $greaterSelectedValue = date('Ymd', strtotime('+ 1 day')); | |
193 | } | |
194 | elseif ($type == 'contact') { | |
195 | $selectedValue = $this->optionGroup[$type]['values'][1]; | |
196 | $notselectedValue = $this->optionGroup[$type]['values'][0]; | |
ec28b24d | 197 | } |
872a35c1 | 198 | elseif ($type == 'boolean') { |
199 | $selectedValue = 1; | |
200 | $notselectedValue = 0; | |
201 | } | |
ec28b24d | 202 | else { |
203 | $selectedValue = $this->optionGroup[$type]['values'][0]; | |
204 | $notselectedValue = $this->optionGroup[$type]['values'][$count]; | |
a6d226f4 | 205 | if (in_array(">", $sqlOps)) { |
206 | $greaterSelectedValue = $selectedValue + 1; | |
207 | $lesserSelectedValue = $selectedValue - 1; | |
208 | } | |
ec28b24d | 209 | } |
6a488035 | 210 | |
0ec36ef1 JP |
211 | $params = [ |
212 | 'entity_id' => $contactId, | |
213 | 'custom_' . $customId => $selectedValue, | |
214 | "custom_{$this->_customFieldID}" => "Test String Value for {$this->_customFieldID}", | |
215 | ]; | |
ec28b24d | 216 | $this->callAPISuccess('CustomValue', 'create', $params); |
6c6e6187 | 217 | |
bc3c9f57 JP |
218 | //Test for different return value syntax. |
219 | $returnValues = [ | |
220 | ['return' => "custom_{$customId}"], | |
221 | ['return' => ["custom_{$customId}"]], | |
222 | ["return.custom_{$customId}" => 1], | |
0ec36ef1 JP |
223 | ['return' => ["custom_{$customId}", "custom_{$this->_customFieldID}"]], |
224 | ["return.custom_{$customId}" => 1, "return.custom_{$this->_customFieldID}" => 1], | |
bc3c9f57 | 225 | ]; |
0ec36ef1 | 226 | foreach ($returnValues as $key => $val) { |
bc3c9f57 | 227 | $params = array_merge($val, [ |
bc3c9f57 JP |
228 | 'entity_id' => $contactId, |
229 | ]); | |
230 | $customValue = $this->callAPISuccess('CustomValue', 'get', $params); | |
231 | if (is_array($selectedValue)) { | |
232 | $expected = array_values($selectedValue); | |
0ec36ef1 | 233 | $this->checkArrayEquals($expected, $customValue['values'][$customId]['latest']); |
bc3c9f57 JP |
234 | } |
235 | elseif ($type == 'date') { | |
0ec36ef1 | 236 | $this->assertEquals($selectedValue, date('Ymd', strtotime(str_replace('.', '/', $customValue['values'][$customId]['latest'])))); |
bc3c9f57 JP |
237 | } |
238 | else { | |
0ec36ef1 JP |
239 | $this->assertEquals($selectedValue, $customValue['values'][$customId]['latest']); |
240 | } | |
241 | if ($key > 2) { | |
242 | $this->assertEquals("Test String Value for {$this->_customFieldID}", $customValue['values'][$this->_customFieldID]['latest']); | |
bc3c9f57 JP |
243 | } |
244 | } | |
245 | ||
ec28b24d | 246 | foreach ($sqlOps as $op) { |
a6d226f4 | 247 | $qillOp = CRM_Utils_Array::value($op, CRM_Core_SelectValues::getSearchBuilderOperators(), $op); |
ec28b24d | 248 | switch ($op) { |
a6d226f4 | 249 | case '=': |
9099cab3 | 250 | $result = $this->callAPISuccess('Contact', 'Get', ['custom_' . $customId => (is_array($selectedValue) ? implode(CRM_Core_DAO::VALUE_SEPARATOR, $selectedValue) : $selectedValue)]); |
a6d226f4 | 251 | $this->assertEquals($contactId, $result['id']); |
a6d226f4 | 252 | break; |
842ee194 | 253 | |
ec28b24d | 254 | case '!=': |
9099cab3 | 255 | $result = $this->callAPISuccess('Contact', 'Get', ['custom_' . $customId => [$op => $notselectedValue]]); |
a4a68fa4 | 256 | $this->assertEquals(TRUE, array_key_exists($contactId, $result['values'])); |
ec28b24d | 257 | break; |
6c6e6187 | 258 | |
ec28b24d | 259 | case '>': |
260 | case '<': | |
261 | case '>=': | |
262 | case '<=': | |
a6d226f4 | 263 | if ($isSerialized) { |
e255b57a | 264 | break; |
a6d226f4 | 265 | } |
ec28b24d | 266 | // To be precise in for these operator we can't just rely on one contact, |
267 | // hence creating multiple contact with custom value less/more then $selectedValue respectively | |
9099cab3 | 268 | $result = $this->callAPISuccess('Contact', 'create', ['contact_type' => 'Individual', 'email' => substr(sha1(rand()), 0, 7) . 'man2@yahoo.com']); |
ec28b24d | 269 | $contactId2 = $result['id']; |
9099cab3 | 270 | $this->callAPISuccess('CustomValue', 'create', ['entity_id' => $contactId2, 'custom_' . $customId => $lesserSelectedValue]); |
842ee194 | 271 | |
ec28b24d | 272 | if ($op == '>') { |
9099cab3 | 273 | $result = $this->callAPISuccess('Contact', 'Get', ['custom_' . $customId => [$op => $lesserSelectedValue]]); |
ec28b24d | 274 | $this->assertEquals($contactId, $result['id']); |
275 | } | |
276 | elseif ($op == '<') { | |
9099cab3 | 277 | $result = $this->callAPISuccess('Contact', 'Get', ['custom_' . $customId => [$op => $selectedValue]]); |
ec28b24d | 278 | $this->assertEquals($contactId2, $result['id']); |
279 | } | |
280 | else { | |
9099cab3 | 281 | $result = $this->callAPISuccess('Contact', 'create', ['contact_type' => 'Individual', 'email' => substr(sha1(rand()), 0, 7) . 'man3@yahoo.com']); |
ec28b24d | 282 | $contactId3 = $result['id']; |
9099cab3 | 283 | $this->callAPISuccess('CustomValue', 'create', ['entity_id' => $contactId3, 'custom_' . $customId => $greaterSelectedValue]); |
842ee194 | 284 | |
9099cab3 | 285 | $result = $this->callAPISuccess('Contact', 'Get', ['custom_' . $customId => [$op => $selectedValue]]); |
ec28b24d | 286 | |
287 | $this->assertEquals($contactId, $result['values'][$contactId]['id']); | |
288 | if ($op == '>=') { | |
289 | $this->assertEquals($contactId3, $result['values'][$contactId3]['id']); | |
290 | } | |
291 | else { | |
292 | $this->assertEquals($contactId2, $result['values'][$contactId2]['id']); | |
293 | } | |
9099cab3 | 294 | $this->callAPISuccess('contact', 'delete', ['id' => $contactId3]); |
ec28b24d | 295 | } |
296 | ||
9099cab3 | 297 | $this->callAPISuccess('contact', 'delete', ['id' => $contactId2]); |
ec28b24d | 298 | break; |
299 | ||
300 | case 'IN': | |
9099cab3 | 301 | $result = $this->callAPISuccess('Contact', 'Get', ['custom_' . $customId => [$op => (array) $selectedValue]]); |
ec28b24d | 302 | $this->assertEquals($contactId, $result['id']); |
303 | break; | |
304 | ||
305 | case 'NOT IN': | |
9099cab3 | 306 | $result = $this->callAPISuccess('Contact', 'Get', ['custom_' . $customId => [$op => (array) $notselectedValue]]); |
ec28b24d | 307 | $this->assertEquals($contactId, $result['id']); |
308 | break; | |
309 | ||
310 | case 'LIKE': | |
a6d226f4 | 311 | $selectedValue = is_array($selectedValue) ? $selectedValue[0] : $selectedValue; |
9099cab3 | 312 | $result = $this->callAPISuccess('Contact', 'Get', ['custom_' . $customId => [$op => "%$selectedValue%"]]); |
ec28b24d | 313 | $this->assertEquals($contactId, $result['id']); |
314 | break; | |
6a488035 | 315 | |
ec28b24d | 316 | case 'NOT LIKE': |
9099cab3 | 317 | $result = $this->callAPISuccess('Contact', 'Get', ['custom_' . $customId => [$op => $notselectedValue]]); |
ec28b24d | 318 | $this->assertEquals($contactId, $result['id']); |
319 | break; | |
6c6e6187 | 320 | |
ec28b24d | 321 | case 'IS NULL': |
9099cab3 | 322 | $result = $this->callAPISuccess('Contact', 'Get', ['custom_' . $customId => [$op => 1]]); |
ec28b24d | 323 | $this->assertEquals(FALSE, array_key_exists($contactId, $result['values'])); |
324 | break; | |
842ee194 | 325 | |
ec28b24d | 326 | case 'IS NOT NULL': |
9099cab3 | 327 | $result = $this->callAPISuccess('Contact', 'Get', ['custom_' . $customId => [$op => 1]]); |
ec28b24d | 328 | $this->assertEquals($contactId, $result['id']); |
329 | break; | |
330 | } | |
331 | } | |
6c6e6187 | 332 | |
9099cab3 | 333 | $this->callAPISuccess('Contact', 'delete', ['id' => $contactId]); |
842ee194 | 334 | } |
96025800 | 335 | |
58eaa092 CW |
336 | /** |
337 | * Ensure custom data is updated when option values are modified | |
338 | * | |
339 | * @link https://issues.civicrm.org/jira/browse/CRM-11856 | |
340 | * | |
341 | * @throws \CiviCRM_API3_Exception | |
342 | */ | |
343 | public function testAlterOptionValue() { | |
6fca1a34 | 344 | $this->_populateOptionAndCustomGroup('string'); |
345 | ||
9099cab3 | 346 | $selectField = $this->customFieldCreate([ |
6fca1a34 | 347 | 'custom_group_id' => $this->ids['string']['custom_group_id'], |
58eaa092 CW |
348 | 'label' => 'Custom Select', |
349 | 'html_type' => 'Select', | |
6fca1a34 | 350 | 'option_group_id' => $this->optionGroup['string']['id'], |
9099cab3 CW |
351 | ]); |
352 | $selectField = civicrm_api3('customField', 'getsingle', ['id' => $selectField['id']]); | |
353 | $radioField = $this->customFieldCreate([ | |
6fca1a34 | 354 | 'custom_group_id' => $this->ids['string']['custom_group_id'], |
58eaa092 CW |
355 | 'label' => 'Custom Radio', |
356 | 'html_type' => 'Radio', | |
357 | 'option_group_id' => $selectField['option_group_id'], | |
9099cab3 CW |
358 | ]); |
359 | $multiSelectField = $this->customFieldCreate([ | |
6fca1a34 | 360 | 'custom_group_id' => $this->ids['string']['custom_group_id'], |
58eaa092 CW |
361 | 'label' => 'Custom Multi-Select', |
362 | 'html_type' => 'Multi-Select', | |
363 | 'option_group_id' => $selectField['option_group_id'], | |
9099cab3 | 364 | ]); |
58eaa092 CW |
365 | $selectName = 'custom_' . $selectField['id']; |
366 | $radioName = 'custom_' . $radioField['id']; | |
367 | $multiSelectName = 'custom_' . $multiSelectField['id']; | |
6fca1a34 | 368 | $controlFieldName = 'custom_' . $this->ids['string']['custom_field_id']; |
58eaa092 | 369 | |
9099cab3 | 370 | $params = [ |
58eaa092 CW |
371 | 'first_name' => 'abc4', |
372 | 'last_name' => 'xyz4', | |
373 | 'contact_type' => 'Individual', | |
374 | 'email' => 'man4@yahoo.com', | |
6fca1a34 | 375 | $selectName => $this->optionGroup['string']['values'][0], |
376 | $multiSelectName => $this->optionGroup['string']['values'], | |
377 | $radioName => $this->optionGroup['string']['values'][1], | |
58eaa092 | 378 | // The control group in a science experiment should be unaffected |
6fca1a34 | 379 | $controlFieldName => $this->optionGroup['string']['values'][2], |
9099cab3 | 380 | ]; |
58eaa092 CW |
381 | |
382 | $contact = $this->callAPISuccess('Contact', 'create', $params); | |
383 | ||
9099cab3 | 384 | $result = $this->callAPISuccess('Contact', 'getsingle', [ |
58eaa092 | 385 | 'id' => $contact['id'], |
9099cab3 CW |
386 | 'return' => [$selectName, $multiSelectName], |
387 | ]); | |
6fca1a34 | 388 | $this->assertEquals($params[$selectName], $result[$selectName]); |
389 | $this->assertEquals($params[$multiSelectName], $result[$multiSelectName]); | |
58eaa092 | 390 | |
9099cab3 | 391 | $this->callAPISuccess('OptionValue', 'create', [ |
58eaa092 CW |
392 | 'value' => 'one-modified', |
393 | 'option_group_id' => $selectField['option_group_id'], | |
1453c6db | 394 | 'label' => 'string 1', |
9099cab3 | 395 | 'options' => [ |
1453c6db | 396 | 'match-mandatory' => ['option_group_id', 'label'], |
9099cab3 CW |
397 | ], |
398 | ]); | |
58eaa092 | 399 | |
9099cab3 | 400 | $result = $this->callAPISuccess('Contact', 'getsingle', [ |
58eaa092 | 401 | 'id' => $contact['id'], |
9099cab3 CW |
402 | 'return' => [$selectName, $multiSelectName, $controlFieldName, $radioName], |
403 | ]); | |
58eaa092 CW |
404 | // Ensure the relevant fields have been updated |
405 | $this->assertEquals('one-modified', $result[$selectName]); | |
9099cab3 | 406 | $this->assertEquals(['one-modified', $params[$radioName], $params[$controlFieldName]], $result[$multiSelectName]); |
58eaa092 | 407 | // This field should not have changed because we didn't alter this option |
6fca1a34 | 408 | $this->assertEquals($params[$radioName], $result[$radioName]); |
58eaa092 | 409 | // This should not have changed because this field doesn't use the affected option group |
6fca1a34 | 410 | $this->assertEquals($params[$controlFieldName], $result[$controlFieldName]); |
f36d17d2 | 411 | // Add test of proof that multivalue fields. |
9099cab3 | 412 | $this->callAPISuccess('CustomValue', 'create', [ |
f36d17d2 | 413 | 'entity_id' => $contact['id'], |
9099cab3 CW |
414 | $multiSelectName => [$params[$radioName], $params[$controlFieldName]], |
415 | ]); | |
416 | $result = $this->callAPISuccess('Contact', 'getsingle', [ | |
f36d17d2 | 417 | 'id' => $contact['id'], |
9099cab3 CW |
418 | 'return' => [$selectName, $multiSelectName, $controlFieldName, $radioName], |
419 | ]); | |
f36d17d2 | 420 | |
9099cab3 | 421 | $this->assertEquals([$params[$radioName], $params[$controlFieldName]], $result[$multiSelectName]); |
58eaa092 CW |
422 | } |
423 | ||
24871985 | 424 | public function testGettree() { |
9099cab3 | 425 | $cg = $this->callAPISuccess('CustomGroup', 'create', [ |
24871985 CW |
426 | 'title' => 'TestGettree', |
427 | 'extends' => 'Individual', | |
9099cab3 CW |
428 | ]); |
429 | $cf = $this->callAPISuccess('CustomField', 'create', [ | |
24871985 CW |
430 | 'custom_group_id' => $cg['id'], |
431 | 'label' => 'Got Options', | |
432 | 'name' => 'got_options', | |
433 | "data_type" => "String", | |
434 | "html_type" => "Multi-Select", | |
9099cab3 CW |
435 | 'option_values' => ['1' => 'One', '2' => 'Two', '3' => 'Three'], |
436 | ]); | |
24871985 | 437 | $fieldName = 'custom_' . $cf['id']; |
9099cab3 | 438 | $contact = $this->individualCreate([$fieldName => ['2', '3']]); |
0b330e6d CW |
439 | |
440 | // Verify values are formatted correctly | |
9099cab3 CW |
441 | $tree = $this->callAPISuccess('CustomValue', 'gettree', ['entity_type' => 'Contact', 'entity_id' => $contact]); |
442 | $this->assertEquals(['2', '3'], $tree['values']['TestGettree']['fields']['got_options']['value']['data']); | |
24871985 | 443 | $this->assertEquals('Two, Three', $tree['values']['TestGettree']['fields']['got_options']['value']['display']); |
0b330e6d CW |
444 | |
445 | // Try limiting the return params | |
9099cab3 | 446 | $tree = $this->callAPISuccess('CustomValue', 'gettree', [ |
0b330e6d CW |
447 | 'entity_type' => 'Contact', |
448 | 'entity_id' => $contact, | |
9099cab3 | 449 | 'return' => [ |
0b330e6d CW |
450 | 'custom_group.id', |
451 | 'custom_field.id', | |
9099cab3 CW |
452 | ], |
453 | ]); | |
454 | $this->assertEquals(['2', '3'], $tree['values']['TestGettree']['fields']['got_options']['value']['data']); | |
e6446db2 | 455 | $this->assertEquals('Two, Three', $tree['values']['TestGettree']['fields']['got_options']['value']['display']); |
9099cab3 | 456 | $this->assertEquals(['id', 'fields'], array_keys($tree['values']['TestGettree'])); |
0b330e6d | 457 | |
e6446db2 | 458 | // Ensure display values are returned even if data is not |
9099cab3 | 459 | $tree = $this->callAPISuccess('CustomValue', 'gettree', [ |
e6446db2 CW |
460 | 'entity_type' => 'Contact', |
461 | 'entity_id' => $contact, | |
9099cab3 | 462 | 'return' => [ |
e6446db2 | 463 | 'custom_value.display', |
9099cab3 CW |
464 | ], |
465 | ]); | |
e6446db2 CW |
466 | $this->assertEquals('Two, Three', $tree['values']['TestGettree']['fields']['got_options']['value']['display']); |
467 | $this->assertFalse(isset($tree['values']['TestGettree']['fields']['got_options']['value']['data'])); | |
468 | ||
0b330e6d CW |
469 | // Verify that custom set appears for individuals even who don't have any custom data |
470 | $contact2 = $this->individualCreate(); | |
9099cab3 | 471 | $tree = $this->callAPISuccess('CustomValue', 'gettree', ['entity_type' => 'Contact', 'entity_id' => $contact2]); |
0b330e6d CW |
472 | $this->assertArrayHasKey('TestGettree', $tree['values']); |
473 | ||
474 | // Verify that custom set doesn't appear for other contact types | |
475 | $org = $this->organizationCreate(); | |
9099cab3 | 476 | $tree = $this->callAPISuccess('CustomValue', 'gettree', ['entity_type' => 'Contact', 'entity_id' => $org]); |
0b330e6d CW |
477 | $this->assertArrayNotHasKey('TestGettree', $tree['values']); |
478 | ||
479 | } | |
480 | ||
481 | public function testGettree_getfields() { | |
9099cab3 | 482 | $fields = $this->callAPISuccess('CustomValue', 'getfields', ['api_action' => 'gettree']); |
0b330e6d CW |
483 | $fields = $fields['values']; |
484 | $this->assertTrue((bool) $fields['entity_id']['api.required']); | |
485 | $this->assertTrue((bool) $fields['entity_type']['api.required']); | |
486 | $this->assertEquals('custom_group.id', $fields['custom_group.id']['name']); | |
487 | $this->assertEquals('custom_field.id', $fields['custom_field.id']['name']); | |
488 | $this->assertEquals('custom_value.id', $fields['custom_value.id']['name']); | |
24871985 CW |
489 | } |
490 | ||
63b7d442 AS |
491 | /** |
492 | * Test that custom fields in greeting strings are updated. | |
493 | */ | |
d20c5e6c | 494 | public function testUpdateCustomGreetings(): void { |
63b7d442 | 495 | // Create a custom group with one field. |
9099cab3 | 496 | $customGroupResult = $this->callAPISuccess('CustomGroup', 'create', [ |
63b7d442 | 497 | 'sequential' => 1, |
d20c5e6c EM |
498 | 'title' => 'test custom group', |
499 | 'extends' => 'Individual', | |
9099cab3 CW |
500 | ]); |
501 | $customFieldResult = $this->callAPISuccess('CustomField', 'create', [ | |
63b7d442 AS |
502 | 'custom_group_id' => $customGroupResult['id'], |
503 | 'label' => "greeting test", | |
504 | 'data_type' => "String", | |
505 | 'html_type' => "Text", | |
9099cab3 | 506 | ]); |
63b7d442 AS |
507 | $customFieldId = $customFieldResult['id']; |
508 | ||
509 | // Create a contact with an email greeting format that includes the new custom field. | |
9099cab3 | 510 | $contactResult = $this->callAPISuccess('Contact', 'create', [ |
63b7d442 | 511 | 'contact_type' => 'Individual', |
d20c5e6c EM |
512 | 'email' => 'her@yahoo.com', |
513 | 'email_greeting_id' => 'Customized', | |
63b7d442 | 514 | 'email_greeting_custom' => "Dear {contact.custom_{$customFieldId}}", |
9099cab3 | 515 | ]); |
63b7d442 AS |
516 | $cid = $contactResult['id']; |
517 | ||
518 | // Define testing values. | |
d20c5e6c | 519 | $testGreetingValue = 'Dear custom field'; |
63b7d442 AS |
520 | |
521 | // Update contact's custom field with CustomValue.create | |
d20c5e6c | 522 | $this->callAPISuccess('CustomValue', 'create', [ |
63b7d442 | 523 | 'entity_id' => $cid, |
d20c5e6c EM |
524 | "custom_{$customFieldId}" => 'custom field', |
525 | 'entity_table' => 'civicrm_contact', | |
9099cab3 | 526 | ]); |
63b7d442 | 527 | |
9099cab3 | 528 | $contact = $this->callAPISuccessGetSingle('Contact', ['id' => $cid, 'return' => 'email_greeting']); |
63b7d442 AS |
529 | $this->assertEquals($testGreetingValue, $contact['email_greeting_display']); |
530 | ||
531 | } | |
532 | ||
5498def2 T |
533 | /** |
534 | * Creates a multi-valued custom field set and creates a contact with mutliple values for it. | |
535 | * | |
536 | * @return array | |
537 | */ | |
538 | private function _testGetCustomValueMultiple() { | |
539 | $fieldIDs = $this->CustomGroupMultipleCreateWithFields(); | |
540 | $customFieldValues = []; | |
541 | foreach ($fieldIDs['custom_field_id'] as $id) { | |
542 | $customFieldValues["custom_{$id}"] = "field_{$id}_value_1"; | |
543 | } | |
544 | $this->assertNotEmpty($customFieldValues); | |
545 | $contactParams = [ | |
546 | 'first_name' => 'Jane', | |
547 | 'last_name' => 'Doe', | |
548 | 'contact_type' => 'Individual', | |
549 | ]; | |
550 | $contact = $this->callAPISuccess('Contact', 'create', array_merge($contactParams, $customFieldValues)); | |
551 | foreach ($fieldIDs['custom_field_id'] as $id) { | |
552 | $customFieldValues["custom_{$id}"] = "field_{$id}_value_2"; | |
553 | } | |
554 | $result = $this->callAPISuccess('Contact', 'create', array_merge(['id' => $contact['id']], $customFieldValues)); | |
555 | return [ | |
556 | $contact['id'], | |
557 | $customFieldValues, | |
558 | ]; | |
559 | } | |
560 | ||
561 | /** | |
562 | * Test that specific custom values can be retrieved while using return with comma separated values as genererated by the api explorer. | |
563 | * ['return' => 'custom_1,custom_2'] | |
564 | */ | |
565 | public function testGetCustomValueReturnMultipleApiExplorer() { | |
56fbe1df | 566 | [$cid, $customFieldValues] = $this->_testGetCustomValueMultiple(); |
5498def2 T |
567 | $result = $this->callAPISuccess('CustomValue', 'get', [ |
568 | 'return' => implode(',', array_keys($customFieldValues)), | |
569 | 'entity_id' => $cid, | |
570 | ]); | |
571 | $this->assertEquals(count($customFieldValues), $result['count']); | |
572 | } | |
573 | ||
574 | /** | |
575 | * Test that specific custom values can be retrieved while using return with array style syntax. | |
576 | * ['return => ['custom_1', 'custom_2']] | |
577 | */ | |
578 | public function testGetCustomValueReturnMultipleArray() { | |
56fbe1df | 579 | [$cid, $customFieldValues] = $this->_testGetCustomValueMultiple(); |
5498def2 T |
580 | $result = $this->callAPISuccess('CustomValue', 'get', [ |
581 | 'return' => array_keys($customFieldValues), | |
582 | 'entity_id' => $cid, | |
583 | ]); | |
584 | $this->assertEquals(count($customFieldValues), $result['count']); | |
585 | } | |
586 | ||
587 | /** | |
588 | * Test that specific custom values can be retrieved while using a list of return parameters. | |
589 | * [['return.custom_1' => '1'], ['return.custom_2' => '1']] | |
590 | */ | |
591 | public function testGetCustomValueReturnMultipleList() { | |
56fbe1df | 592 | [$cid, $customFieldValues] = $this->_testGetCustomValueMultiple(); |
5498def2 T |
593 | $returnArray = []; |
594 | foreach ($customFieldValues as $field => $value) { | |
595 | $returnArray["return.{$field}"] = 1; | |
596 | } | |
597 | $result = $this->callAPISuccess('CustomValue', 'get', array_merge($returnArray, ['entity_id' => $cid])); | |
598 | $this->assertEquals(count($customFieldValues), $result['count']); | |
599 | } | |
600 | ||
afbd0c22 JP |
601 | /** |
602 | * Test getdisplayvalue api and verify if it returns | |
603 | * the custom text for display. | |
604 | */ | |
605 | public function testGetDisplayValue() { | |
56fbe1df | 606 | [$cid, $customFieldValues] = $this->_testGetCustomValueMultiple(); |
afbd0c22 | 607 | foreach ($customFieldValues as $field => $value) { |
56fbe1df | 608 | [, $customFieldID] = explode("_", $field); |
afbd0c22 JP |
609 | $result = $this->callAPISuccess('CustomValue', 'getdisplayvalue', [ |
610 | 'entity_id' => $cid, | |
611 | 'custom_field_id' => $customFieldID, | |
612 | ]); | |
613 | $expectedValue = [ | |
614 | 'display' => $value, | |
615 | 'raw' => $value, | |
616 | ]; | |
617 | $this->checkArrayEquals($result['values'][$customFieldID], $expectedValue); | |
618 | ||
619 | $customDisplayValue = $this->callAPISuccess('CustomValue', 'getdisplayvalue', [ | |
620 | 'entity_id' => $cid, | |
621 | 'custom_field_id' => $customFieldID, | |
622 | 'custom_field_value' => "Test Custom Display - {$value}", | |
623 | ]); | |
624 | $expectedValue = [ | |
625 | 'display' => "Test Custom Display - {$value}", | |
626 | 'raw' => "Test Custom Display - {$value}", | |
627 | ]; | |
628 | $this->checkArrayEquals($customDisplayValue['values'][$customFieldID], $expectedValue); | |
629 | } | |
630 | } | |
631 | ||
ef10e0b5 | 632 | } |