unit test fixes 4.7beta4
[civicrm-core.git] / tests / phpunit / api / v3 / CustomValueTest.php
CommitLineData
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
28require_once 'CiviTest/CiviUnitTestCase.php';
e9479dcf
EM
29
30/**
31 * Class api_v3_CustomValueTest
32 */
6a488035 33class 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}