Commit | Line | Data |
---|---|---|
6a488035 | 1 | <?php |
fc928539 | 2 | /** |
92915c55 | 3 | * +--------------------------------------------------------------------+ |
81621fee | 4 | * | CiviCRM version 4.7 | |
92915c55 | 5 | * +--------------------------------------------------------------------+ |
e7112fa7 | 6 | * | Copyright CiviCRM LLC (c) 2004-2015 | |
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 TO |
27 | |
28 | require_once 'CiviTest/CiviUnitTestCase.php'; | |
e9479dcf EM |
29 | |
30 | /** | |
31 | * Class api_v3_CustomValueTest | |
32 | */ | |
6a488035 | 33 | class api_v3_CustomValueTest extends CiviUnitTestCase { |
6c6e6187 | 34 | protected $_apiversion = 3; |
6a488035 | 35 | protected $ids; |
ec28b24d | 36 | protected $optionGroup; |
b7c9bc4c | 37 | |
6a488035 TO |
38 | public $DBResetRequired = FALSE; |
39 | ||
00be9182 | 40 | public function setUp() { |
6a488035 | 41 | parent::setUp(); |
ec28b24d | 42 | } |
43 | ||
6fca1a34 | 44 | public function _populateOptionAndCustomGroup($type = NULL) { |
ec28b24d | 45 | $dataValues = array( |
8007b543 | 46 | 'integer' => array(1, 2, 3), |
47 | 'number' => array(10.11, 20.22, 30.33), | |
ec28b24d | 48 | 'string' => array(substr(sha1(rand()), 0, 4), substr(sha1(rand()), 0, 3), substr(sha1(rand()), 0, 2)), |
872a35c1 | 49 | 'country' => array_rand(CRM_Core_PseudoConstant::country(FALSE, FALSE), 3), |
ec28b24d | 50 | 'state_province' => array_rand(CRM_Core_PseudoConstant::stateProvince(FALSE, FALSE), 3), |
51 | 'date' => NULL, | |
a6d226f4 | 52 | 'contact' => NULL, |
872a35c1 | 53 | 'boolean' => NULL, |
6a488035 | 54 | ); |
ec28b24d | 55 | |
6fca1a34 | 56 | $dataValues = !empty($type) ? array($type => $dataValues[$type]) : $dataValues; |
57 | ||
ec28b24d | 58 | foreach ($dataValues as $dataType => $values) { |
a6d226f4 | 59 | $this->optionGroup[$dataType] = array('values' => $values); |
ec28b24d | 60 | if (!empty($values)) { |
ec28b24d | 61 | $result = $this->callAPISuccess('OptionGroup', 'create', |
62 | array( | |
63 | 'name' => "{$dataType}_group", | |
64 | 'api.option_value.create' => array('label' => "$dataType 1", 'value' => $values[0]), | |
65 | 'api.option_value.create.1' => array('label' => "$dataType 2", 'value' => $values[1]), | |
66 | 'api.option_value.create.2' => array('label' => "$dataType 3", 'value' => $values[2]), | |
67 | ) | |
68 | ); | |
69 | $this->optionGroup[$dataType]['id'] = $result['id']; | |
70 | } | |
a6d226f4 | 71 | elseif ($dataType == 'contact') { |
f819588f | 72 | for ($i = 0; $i < 3; $i++) { |
73 | $result = $this->callAPISuccess('Contact', 'create', array('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() { |
6a488035 TO |
83 | $tablesToTruncate = array( |
84 | 'civicrm_email', | |
85 | 'civicrm_custom_field', | |
86 | 'civicrm_custom_group', | |
87 | 'civicrm_contact', | |
88 | ); | |
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'])) { | |
97 | $this->callAPISuccess('OptionGroup', 'delete', array('id' => $value['id'])); | |
98 | } | |
99 | } | |
100 | } | |
6a488035 TO |
101 | } |
102 | ||
103 | public function testCreateCustomValue() { | |
6fca1a34 | 104 | $this->_populateOptionAndCustomGroup(); |
105 | ||
ec28b24d | 106 | $customFieldDataType = CRM_Core_BAO_CustomField::dataType(); |
107 | $dataToHtmlTypes = CRM_Core_BAO_CustomField::dataToHtml(); | |
108 | $count = 0; | |
6a488035 | 109 | |
ec28b24d | 110 | foreach ($customFieldDataType as $dataType => $label) { |
ec28b24d | 111 | switch ($dataType) { |
0170d873 | 112 | case 'Country': |
113 | case 'StateProvince': | |
114 | $this->foreignKeyChecksOff(); | |
ec28b24d | 115 | case 'String': |
116 | case 'Link': | |
117 | case 'Int': | |
118 | case 'Float': | |
119 | case 'Money': | |
872a35c1 | 120 | case 'Date': |
872a35c1 | 121 | case 'Boolean': |
122 | ||
123 | //Based on the custom field data-type choose desired SQL operators(to test with) and basic $type | |
ec28b24d | 124 | if (in_array($dataType, array('String', 'Link'))) { |
872a35c1 | 125 | $validSQLOperators = array('=', '!=', 'IN', 'NOT IN', 'LIKE', 'NOT LIKE', 'IS NOT NULL', 'IS NULL'); |
ec28b24d | 126 | $type = 'string'; |
127 | } | |
872a35c1 | 128 | elseif ($dataType == 'Boolean') { |
129 | $validSQLOperators = array('=', '!=', 'IS NOT NULL', 'IS NULL'); | |
130 | $type = 'boolean'; | |
131 | } | |
ec28b24d | 132 | else { |
872a35c1 | 133 | if ($dataType == 'Country') { |
134 | $type = 'country'; | |
135 | } | |
136 | elseif ($dataType == 'StateProvince') { | |
ec28b24d | 137 | $type = 'state_province'; |
138 | } | |
a6d226f4 | 139 | elseif ($dataType == 'ContactReference') { |
140 | $type = 'contact'; | |
141 | } | |
142 | elseif ($dataType == 'Date') { | |
143 | $type = 'date'; | |
144 | } | |
ec28b24d | 145 | else { |
a6d226f4 | 146 | $type = $dataType == 'Int' ? 'integer' : 'number'; |
ec28b24d | 147 | } |
872a35c1 | 148 | $validSQLOperators = array('=', '!=', 'IN', 'NOT IN', '<=', '>=', '>', '<', 'IS NOT NULL', 'IS NULL'); |
ec28b24d | 149 | } |
6a488035 | 150 | |
872a35c1 | 151 | //Create custom field of $dataType and html-type $html |
ec28b24d | 152 | foreach ($dataToHtmlTypes[$count] as $html) { |
153 | $params = array( | |
154 | 'custom_group_id' => $this->ids[$type]['custom_group_id'], | |
155 | 'label' => "$dataType - $html", | |
156 | 'data_type' => $dataType, | |
157 | 'html_type' => $html, | |
158 | 'default_value' => NULL, | |
159 | ); | |
872a35c1 | 160 | if (!in_array($html, array('Text', 'TextArea')) && !in_array($dataType, array('Link', 'Date', 'ContactReference', 'Boolean'))) { |
ec28b24d | 161 | $params += array('option_group_id' => $this->optionGroup[$type]['id']); |
162 | } | |
163 | $customField = $this->customFieldCreate($params); | |
872a35c1 | 164 | //Now test with $validSQLOperator SQL operators against its custom value(s) |
165 | $this->_testCustomValue($customField['values'][$customField['id']], $validSQLOperators, $type); | |
ec28b24d | 166 | } |
167 | $count++; | |
168 | break; | |
6a488035 | 169 | |
ec28b24d | 170 | default: |
872a35c1 | 171 | // skipping File data-type |
ec28b24d | 172 | $count++; |
173 | break; | |
174 | } | |
175 | } | |
176 | } | |
6a488035 | 177 | |
ec28b24d | 178 | public function _testCustomValue($customField, $sqlOps, $type) { |
179 | $isSerialized = CRM_Core_BAO_CustomField::isSerialized($customField); | |
180 | $customId = $customField['id']; | |
6a488035 | 181 | $params = array( |
6a488035 | 182 | 'contact_type' => 'Individual', |
ec28b24d | 183 | 'email' => substr(sha1(rand()), 0, 7) . 'man1@yahoo.com', |
6a488035 | 184 | ); |
fc928539 | 185 | $result = $this->callAPISuccess('Contact', 'create', $params); |
ec28b24d | 186 | $contactId = $result['id']; |
6a488035 | 187 | |
8007b543 | 188 | $count = rand(1, 2); |
ec28b24d | 189 | $seperator = CRM_Core_DAO::VALUE_SEPARATOR; |
190 | if ($isSerialized) { | |
191 | $selectedValue = $this->optionGroup[$type]['values']; | |
192 | $notselectedValue = $selectedValue[$count]; | |
193 | unset($selectedValue[$count]); | |
194 | } | |
195 | elseif ($customField['html_type'] == 'Link') { | |
196 | $selectedValue = "http://" . substr(sha1(rand()), 0, 7) . ".com"; | |
197 | $notselectedValue = "http://" . substr(sha1(rand()), 0, 7) . ".com"; | |
198 | } | |
199 | elseif ($type == 'date') { | |
200 | $selectedValue = date('Ymd'); | |
a6d226f4 | 201 | $notselectedValue = $lesserSelectedValue = date('Ymd', strtotime('yesterday')); |
202 | $greaterSelectedValue = date('Ymd', strtotime('+ 1 day')); | |
203 | } | |
204 | elseif ($type == 'contact') { | |
205 | $selectedValue = $this->optionGroup[$type]['values'][1]; | |
206 | $notselectedValue = $this->optionGroup[$type]['values'][0]; | |
ec28b24d | 207 | } |
872a35c1 | 208 | elseif ($type == 'boolean') { |
209 | $selectedValue = 1; | |
210 | $notselectedValue = 0; | |
211 | } | |
ec28b24d | 212 | else { |
213 | $selectedValue = $this->optionGroup[$type]['values'][0]; | |
214 | $notselectedValue = $this->optionGroup[$type]['values'][$count]; | |
a6d226f4 | 215 | if (in_array(">", $sqlOps)) { |
216 | $greaterSelectedValue = $selectedValue + 1; | |
217 | $lesserSelectedValue = $selectedValue - 1; | |
218 | } | |
ec28b24d | 219 | } |
6a488035 | 220 | |
8007b543 | 221 | $params = array('entity_id' => $contactId, 'custom_' . $customId => $selectedValue); |
ec28b24d | 222 | $this->callAPISuccess('CustomValue', 'create', $params); |
6c6e6187 | 223 | |
ec28b24d | 224 | foreach ($sqlOps as $op) { |
a6d226f4 | 225 | $qillOp = CRM_Utils_Array::value($op, CRM_Core_SelectValues::getSearchBuilderOperators(), $op); |
ec28b24d | 226 | switch ($op) { |
a6d226f4 | 227 | case '=': |
228 | $result = $this->callAPISuccess('Contact', 'Get', array('custom_' . $customId => (is_array($selectedValue) ? implode(CRM_Core_DAO::VALUE_SEPARATOR, $selectedValue) : $selectedValue))); | |
229 | $this->assertEquals($contactId, $result['id']); | |
a6d226f4 | 230 | break; |
842ee194 | 231 | |
ec28b24d | 232 | case '!=': |
a6d226f4 | 233 | $result = $this->callAPISuccess('Contact', 'Get', array('custom_' . $customId => array($op => $notselectedValue))); |
a4a68fa4 | 234 | $this->assertEquals(TRUE, array_key_exists($contactId, $result['values'])); |
ec28b24d | 235 | break; |
6c6e6187 | 236 | |
ec28b24d | 237 | case '>': |
238 | case '<': | |
239 | case '>=': | |
240 | case '<=': | |
a6d226f4 | 241 | if ($isSerialized) { |
242 | continue; | |
243 | } | |
ec28b24d | 244 | // To be precise in for these operator we can't just rely on one contact, |
245 | // hence creating multiple contact with custom value less/more then $selectedValue respectively | |
246 | $result = $this->callAPISuccess('Contact', 'create', array('contact_type' => 'Individual', 'email' => substr(sha1(rand()), 0, 7) . 'man2@yahoo.com')); | |
247 | $contactId2 = $result['id']; | |
8007b543 | 248 | $this->callAPISuccess('CustomValue', 'create', array('entity_id' => $contactId2, 'custom_' . $customId => $lesserSelectedValue)); |
842ee194 | 249 | |
ec28b24d | 250 | if ($op == '>') { |
a6d226f4 | 251 | $result = $this->callAPISuccess('Contact', 'Get', array('custom_' . $customId => array($op => $lesserSelectedValue))); |
ec28b24d | 252 | $this->assertEquals($contactId, $result['id']); |
253 | } | |
254 | elseif ($op == '<') { | |
a6d226f4 | 255 | $result = $this->callAPISuccess('Contact', 'Get', array('custom_' . $customId => array($op => $selectedValue))); |
ec28b24d | 256 | $this->assertEquals($contactId2, $result['id']); |
257 | } | |
258 | else { | |
259 | $result = $this->callAPISuccess('Contact', 'create', array('contact_type' => 'Individual', 'email' => substr(sha1(rand()), 0, 7) . 'man3@yahoo.com')); | |
260 | $contactId3 = $result['id']; | |
8007b543 | 261 | $this->callAPISuccess('CustomValue', 'create', array('entity_id' => $contactId3, 'custom_' . $customId => $greaterSelectedValue)); |
842ee194 | 262 | |
a6d226f4 | 263 | $result = $this->callAPISuccess('Contact', 'Get', array('custom_' . $customId => array($op => $selectedValue))); |
ec28b24d | 264 | |
265 | $this->assertEquals($contactId, $result['values'][$contactId]['id']); | |
266 | if ($op == '>=') { | |
267 | $this->assertEquals($contactId3, $result['values'][$contactId3]['id']); | |
268 | } | |
269 | else { | |
270 | $this->assertEquals($contactId2, $result['values'][$contactId2]['id']); | |
271 | } | |
272 | $this->callAPISuccess('contact', 'delete', array('id' => $contactId3)); | |
273 | } | |
274 | ||
275 | $this->callAPISuccess('contact', 'delete', array('id' => $contactId2)); | |
276 | break; | |
277 | ||
278 | case 'IN': | |
a6d226f4 | 279 | $result = $this->callAPISuccess('Contact', 'Get', array('custom_' . $customId => array($op => (array) $selectedValue))); |
ec28b24d | 280 | $this->assertEquals($contactId, $result['id']); |
281 | break; | |
282 | ||
283 | case 'NOT IN': | |
a6d226f4 | 284 | $result = $this->callAPISuccess('Contact', 'Get', array('custom_' . $customId => array($op => (array) $notselectedValue))); |
ec28b24d | 285 | $this->assertEquals($contactId, $result['id']); |
286 | break; | |
287 | ||
288 | case 'LIKE': | |
a6d226f4 | 289 | $selectedValue = is_array($selectedValue) ? $selectedValue[0] : $selectedValue; |
290 | $result = $this->callAPISuccess('Contact', 'Get', array('custom_' . $customId => array($op => "%$selectedValue%"))); | |
ec28b24d | 291 | $this->assertEquals($contactId, $result['id']); |
292 | break; | |
6a488035 | 293 | |
ec28b24d | 294 | case 'NOT LIKE': |
a6d226f4 | 295 | $result = $this->callAPISuccess('Contact', 'Get', array('custom_' . $customId => array($op => $notselectedValue))); |
ec28b24d | 296 | $this->assertEquals($contactId, $result['id']); |
297 | break; | |
6c6e6187 | 298 | |
ec28b24d | 299 | case 'IS NULL': |
a6d226f4 | 300 | $result = $this->callAPISuccess('Contact', 'Get', array('custom_' . $customId => array($op => 1))); |
ec28b24d | 301 | $this->assertEquals(FALSE, array_key_exists($contactId, $result['values'])); |
302 | break; | |
842ee194 | 303 | |
ec28b24d | 304 | case 'IS NOT NULL': |
a6d226f4 | 305 | $result = $this->callAPISuccess('Contact', 'Get', array('custom_' . $customId => array($op => 1))); |
ec28b24d | 306 | $this->assertEquals($contactId, $result['id']); |
307 | break; | |
308 | } | |
309 | } | |
6c6e6187 | 310 | |
ec28b24d | 311 | $this->callAPISuccess('Contact', 'delete', array('id' => $contactId)); |
842ee194 | 312 | } |
96025800 | 313 | |
58eaa092 CW |
314 | /** |
315 | * Ensure custom data is updated when option values are modified | |
316 | * | |
317 | * @link https://issues.civicrm.org/jira/browse/CRM-11856 | |
318 | * | |
319 | * @throws \CiviCRM_API3_Exception | |
320 | */ | |
321 | public function testAlterOptionValue() { | |
6fca1a34 | 322 | $this->_populateOptionAndCustomGroup('string'); |
323 | ||
58eaa092 | 324 | $selectField = $this->customFieldCreate(array( |
6fca1a34 | 325 | 'custom_group_id' => $this->ids['string']['custom_group_id'], |
58eaa092 CW |
326 | 'label' => 'Custom Select', |
327 | 'html_type' => 'Select', | |
6fca1a34 | 328 | 'option_group_id' => $this->optionGroup['string']['id'], |
58eaa092 CW |
329 | )); |
330 | $selectField = civicrm_api3('customField', 'getsingle', array('id' => $selectField['id'])); | |
331 | $radioField = $this->customFieldCreate(array( | |
6fca1a34 | 332 | 'custom_group_id' => $this->ids['string']['custom_group_id'], |
58eaa092 CW |
333 | 'label' => 'Custom Radio', |
334 | 'html_type' => 'Radio', | |
335 | 'option_group_id' => $selectField['option_group_id'], | |
336 | )); | |
337 | $multiSelectField = $this->customFieldCreate(array( | |
6fca1a34 | 338 | 'custom_group_id' => $this->ids['string']['custom_group_id'], |
58eaa092 CW |
339 | 'label' => 'Custom Multi-Select', |
340 | 'html_type' => 'Multi-Select', | |
341 | 'option_group_id' => $selectField['option_group_id'], | |
342 | )); | |
343 | $selectName = 'custom_' . $selectField['id']; | |
344 | $radioName = 'custom_' . $radioField['id']; | |
345 | $multiSelectName = 'custom_' . $multiSelectField['id']; | |
6fca1a34 | 346 | $controlFieldName = 'custom_' . $this->ids['string']['custom_field_id']; |
58eaa092 CW |
347 | |
348 | $params = array( | |
349 | 'first_name' => 'abc4', | |
350 | 'last_name' => 'xyz4', | |
351 | 'contact_type' => 'Individual', | |
352 | 'email' => 'man4@yahoo.com', | |
6fca1a34 | 353 | $selectName => $this->optionGroup['string']['values'][0], |
354 | $multiSelectName => $this->optionGroup['string']['values'], | |
355 | $radioName => $this->optionGroup['string']['values'][1], | |
58eaa092 | 356 | // The control group in a science experiment should be unaffected |
6fca1a34 | 357 | $controlFieldName => $this->optionGroup['string']['values'][2], |
58eaa092 CW |
358 | ); |
359 | ||
360 | $contact = $this->callAPISuccess('Contact', 'create', $params); | |
361 | ||
362 | $result = $this->callAPISuccess('Contact', 'getsingle', array( | |
363 | 'id' => $contact['id'], | |
364 | 'return' => array($selectName, $multiSelectName), | |
365 | )); | |
6fca1a34 | 366 | $this->assertEquals($params[$selectName], $result[$selectName]); |
367 | $this->assertEquals($params[$multiSelectName], $result[$multiSelectName]); | |
58eaa092 CW |
368 | |
369 | $this->callAPISuccess('OptionValue', 'create', array( | |
370 | 'value' => 'one-modified', | |
371 | 'option_group_id' => $selectField['option_group_id'], | |
6fca1a34 | 372 | 'name' => 'string 1', |
58eaa092 CW |
373 | 'options' => array( |
374 | 'match-mandatory' => array('option_group_id', 'name'), | |
375 | ), | |
376 | )); | |
377 | ||
378 | $result = $this->callAPISuccess('Contact', 'getsingle', array( | |
379 | 'id' => $contact['id'], | |
380 | 'return' => array($selectName, $multiSelectName, $controlFieldName, $radioName), | |
381 | )); | |
382 | // Ensure the relevant fields have been updated | |
383 | $this->assertEquals('one-modified', $result[$selectName]); | |
6fca1a34 | 384 | $this->assertEquals(array('one-modified', $params[$radioName], $params[$controlFieldName]), $result[$multiSelectName]); |
58eaa092 | 385 | // This field should not have changed because we didn't alter this option |
6fca1a34 | 386 | $this->assertEquals($params[$radioName], $result[$radioName]); |
58eaa092 | 387 | // This should not have changed because this field doesn't use the affected option group |
6fca1a34 | 388 | $this->assertEquals($params[$controlFieldName], $result[$controlFieldName]); |
58eaa092 CW |
389 | } |
390 | ||
ef10e0b5 | 391 | } |