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