Merge pull request #7717 from yashodha/CRM-17908
[civicrm-core.git] / tests / phpunit / api / v3 / CustomFieldTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2015 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 /**
29 * Test APIv3 civicrm_create_custom_group
30 *
31 * @package CiviCRM
32 */
33 class api_v3_CustomFieldTest extends CiviUnitTestCase {
34 protected $_apiversion;
35
36 public function setUp() {
37 $this->_apiversion = 3;
38 parent::setUp();
39 }
40
41 public function tearDown() {
42 $tablesToTruncate = array(
43 'civicrm_contact',
44 'civicrm_file',
45 'civicrm_entity_file',
46 );
47 // true tells quickCleanup to drop custom_value tables that might have been created in the test
48 $this->quickCleanup($tablesToTruncate, TRUE);
49 }
50
51 /**
52 * Check with no array.
53 */
54 public function testCustomFieldCreateNoArray() {
55 $fieldParams = NULL;
56
57 $customField = $this->callAPIFailure('custom_field', 'create', $fieldParams);
58 $this->assertEquals($customField['error_message'], 'Input variable `params` is not an array');
59 }
60
61 /**
62 * Check with no label.
63 */
64 public function testCustomFieldCreateWithoutLabel() {
65 $customGroup = $this->customGroupCreate(array('extends' => 'Individual', 'title' => 'text_test_group'));
66 $params = array(
67 'custom_group_id' => $customGroup['id'],
68 'name' => 'test_textfield2',
69 'html_type' => 'Text',
70 'data_type' => 'String',
71 'default_value' => 'abc',
72 'weight' => 4,
73 'is_required' => 1,
74 'is_searchable' => 0,
75 'is_active' => 1,
76 );
77
78 $customField = $this->callAPIFailure('custom_field', 'create', $params);
79 $this->assertEquals($customField['error_message'], 'Mandatory key(s) missing from params array: label');
80 }
81
82 /**
83 * Check with edit.
84 */
85 public function testCustomFieldCreateWithEdit() {
86 $customGroup = $this->customGroupCreate(array('extends' => 'Individual', 'title' => 'text_test_group'));
87 $params = array(
88 'custom_group_id' => $customGroup['id'],
89 'name' => 'test_textfield2',
90 'label' => 'Name1',
91 'html_type' => 'Text',
92 'data_type' => 'String',
93 'default_value' => 'abc',
94 'weight' => 4,
95 'is_required' => 1,
96 'is_searchable' => 0,
97 'is_active' => 1,
98 );
99
100 $customField = $this->callAPIAndDocument('custom_field', 'create', $params, __FUNCTION__, __FILE__);
101 $params['id'] = $customField['id'];
102 $customField = $this->callAPISuccess('custom_field', 'create', $params);
103
104 $this->assertNotNull($customField['id']);
105 }
106
107 /**
108 * Check without groupId.
109 */
110 public function testCustomFieldCreateWithoutGroupID() {
111 $fieldParams = array(
112 'name' => 'test_textfield1',
113 'label' => 'Name',
114 'html_type' => 'Text',
115 'data_type' => 'String',
116 'default_value' => 'abc',
117 'weight' => 4,
118 'is_required' => 1,
119 'is_searchable' => 0,
120 'is_active' => 1,
121
122 );
123
124 $customField = $this->callAPIFailure('custom_field', 'create', $fieldParams);
125 $this->assertEquals($customField['error_message'], 'Mandatory key(s) missing from params array: custom_group_id');
126 }
127
128 /**
129 * Check for Each data type: loop through available form input types
130 */
131 public function testCustomFieldCreateAllAvailableFormInputs() {
132 $gid = $this->customGroupCreate(array('extends' => 'Individual', 'title' => 'testAllFormInputs'));
133
134 $dtype = CRM_Core_BAO_CustomField::dataType();
135 $htype = CRM_Core_BAO_CustomField::dataToHtml();
136
137 $n = 0;
138 foreach ($dtype as $dkey => $dvalue) {
139 foreach ($htype[$n] as $hkey => $hvalue) {
140 //echo $dkey."][".$hvalue."\n";
141 $this->_loopingCustomFieldCreateTest($this->_buildParams($gid['id'], $hvalue, $dkey));
142 }
143 $n++;
144 }
145 }
146 /*
147 * Can't figure out the point of this?
148 */
149 /**
150 * @param array $params
151 */
152 public function _loopingCustomFieldCreateTest($params) {
153 $customField = $this->callAPISuccess('custom_field', 'create', $params);
154 $this->assertNotNull($customField['id']);
155 $this->getAndCheck($params, $customField['id'], 'CustomField');
156 }
157
158 /**
159 * @param int $gid
160 * @param $htype
161 * @param $dtype
162 *
163 * @return array
164 */
165 public function _buildParams($gid, $htype, $dtype) {
166 $params = $this->_buildBasicParams($gid, $htype, $dtype);
167 /* //Not Working for any type. Maybe redundant with testCustomFieldCreateWithOptionValues()
168 if ($htype == 'Multi-Select')
169 $params = array_merge($params, array(
170 'option_label' => array( 'Label1','Label2'),
171 'option_value' => array( 'val1', 'val2' ),
172 'option_weight' => array( 1, 2),
173 'option_status' => array( 1, 1),
174 ));
175 */
176
177 return $params;
178 }
179
180 /**
181 * @param int $gid
182 * @param $htype
183 * @param $dtype
184 *
185 * @return array
186 */
187 public function _buildBasicParams($gid, $htype, $dtype) {
188 return array(
189 'custom_group_id' => $gid,
190 'label' => $dtype . $htype,
191 'html_type' => $htype,
192 'data_type' => $dtype,
193 'weight' => 4,
194 'is_required' => 0,
195 'is_searchable' => 0,
196 'is_active' => 1,
197
198 );
199 }
200
201 /**
202 * Test using example code.
203 */
204 /*function testCustomFieldCreateExample( )
205 {
206
207 $customGroup = $this->customGroupCreate('Individual','date_test_group',3);
208 require_once 'api/v3/examples/CustomField/Create.php';
209 $result = custom_field_create_example();
210 $expectedResult = custom_field_create_expectedresult();
211 $this->assertEquals($result,$expectedResult);
212 }*/
213
214 /**
215 * Check with data type - Options with option_values
216 */
217 public function testCustomFieldCreateWithEmptyOptionGroup() {
218 $customGroup = $this->customGroupCreate(array('extends' => 'Contact', 'title' => 'select_test_group'));
219 $params = array(
220 'custom_group_id' => $customGroup['id'],
221 'label' => 'Country',
222 'html_type' => 'Select',
223 'data_type' => 'String',
224 'weight' => 4,
225 'is_required' => 1,
226 'is_searchable' => 0,
227 'is_active' => 1,
228 );
229
230 $customField = $this->callAPISuccess('custom_field', 'create', $params);
231 $this->assertNotNull($customField['id']);
232 $optionGroupID = $this->callAPISuccess('custom_field', 'getvalue', array(
233 'id' => $customField['id'],
234 'return' => 'option_group_id',
235 ));
236
237 $this->assertTrue(is_numeric($optionGroupID) && ($optionGroupID > 0));
238 $optionGroup = $this->callAPISuccess('option_group', 'getsingle', array(
239 'id' => $optionGroupID,
240 ));
241 $this->assertEquals($optionGroup['title'], 'Country');
242 $optionValueCount = $this->callAPISuccess('option_value', 'getcount', array(
243 'option_group_id' => $optionGroupID,
244 ));
245 $this->assertEquals(0, $optionValueCount);
246 }
247
248 /**
249 * Test custom field with existing option group.
250 */
251 public function testCustomFieldExistingOptionGroup() {
252 $customGroup = $this->customGroupCreate(array('extends' => 'Organization', 'title' => 'test_group'));
253 $params = array(
254 'custom_group_id' => $customGroup['id'],
255 // Just to say something:
256 'label' => 'Organization Gender',
257 'html_type' => 'Select',
258 'data_type' => 'Int',
259 'weight' => 4,
260 'is_required' => 1,
261 'is_searchable' => 0,
262 'is_active' => 1,
263 // Option group id 3: gender
264 'option_group_id' => 3,
265 );
266
267 $customField = $this->callAPISuccess('custom_field', 'create', $params);
268 $this->assertNotNull($customField['id']);
269 $optionGroupID = $this->callAPISuccess('custom_field', 'getvalue', array(
270 'id' => $customField['id'],
271 'return' => 'option_group_id',
272 ));
273
274 $this->assertEquals($optionGroupID, 3);
275 }
276
277 /**
278 * Test custom field get works & return param works
279 */
280 public function testCustomFieldGetReturnOptions() {
281 $customGroup = $this->customGroupCreate(array('extends' => 'Individual', 'title' => 'test_group'));
282 $customField = $this->customFieldCreate(array('custom_group_id' => $customGroup['id']));
283
284 $result = $this->callAPISuccess('custom_field', 'getsingle', array(
285 'id' => $customField['id'],
286 'return' => 'data_type',
287 ));
288 $this->assertTrue(array_key_exists('data_type', $result));
289 $this->assertFalse(array_key_exists('custom_group_id', $result));
290 }
291
292 /**
293 * Test custom field get works & return param works
294 */
295 public function testCustomFieldGetReturnArray() {
296 $customGroup = $this->customGroupCreate(array('extends' => 'Individual', 'title' => 'test_group'));
297 $customField = $this->customFieldCreate(array('custom_group_id' => $customGroup['id']));
298
299 $result = $this->callAPISuccess('custom_field', 'getsingle', array(
300 'id' => $customField['id'],
301 'return' => array('data_type'),
302 ));
303 $this->assertTrue(array_key_exists('data_type', $result));
304 $this->assertFalse(array_key_exists('custom_group_id', $result));
305 }
306
307 /**
308 * Test custom field get works & return param works
309 */
310 public function testCustomFieldGetReturnTwoOptions() {
311 $customGroup = $this->customGroupCreate(array('extends' => 'Individual', 'test_group'));
312 $customField = $this->customFieldCreate(array('custom_group_id' => $customGroup['id']));
313
314 $result = $this->callAPISuccess('custom_field', 'getsingle', array(
315 'id' => $customField['id'],
316 'return' => 'data_type, custom_group_id',
317 ));
318 $this->assertTrue(array_key_exists('data_type', $result));
319 $this->assertTrue(array_key_exists('custom_group_id', $result));
320 $this->assertFalse(array_key_exists('label', $result));
321 }
322
323 public function testCustomFieldCreateWithOptionValues() {
324 $customGroup = $this->customGroupCreate(array('extends' => 'Contact', 'title' => 'select_test_group'));
325
326 $option_values = array(
327 array(
328 'weight' => 1,
329 'label' => 'Label1',
330 'value' => 1,
331 'is_active' => 1,
332 ),
333 array(
334 'weight' => 2,
335 'label' => 'Label2',
336 'value' => 2,
337 'is_active' => 1,
338 ),
339 );
340
341 $params = array(
342 'custom_group_id' => $customGroup['id'],
343 'label' => 'Our special field',
344 'html_type' => 'Select',
345 'data_type' => 'String',
346 'weight' => 4,
347 'is_required' => 1,
348 'is_searchable' => 0,
349 'is_active' => 1,
350 'option_values' => $option_values,
351
352 );
353
354 $customField = $this->callAPISuccess('custom_field', 'create', $params);
355
356 $this->assertAPISuccess($customField);
357 $this->assertNotNull($customField['id']);
358 $getFieldsParams = array(
359 'options' => array('get_options' => 'custom_' . $customField['id']),
360 'action' => 'create',
361 );
362 $description = "Demonstrates retrieving metadata with custom field options.";
363 $subfile = "GetFieldsOptions";
364 $fields = $this->callAPIAndDocument('contact', 'getfields', $getFieldsParams, __FUNCTION__, 'ContactTest.php', $description, $subfile);
365 $this->assertArrayHasKey('options', $fields['values']['custom_' . $customField['id']]);
366 $this->assertEquals('Label1', $fields['values']['custom_' . $customField['id']]['options'][1]);
367 $getOptionsArray = array(
368 'field' => 'custom_' . $customField['id'],
369 );
370 $description = "Demonstrates retrieving options for a custom field.";
371 $subfile = "GetOptions";
372 $result = $this->callAPIAndDocument('contact', 'getoptions', $getOptionsArray, __FUNCTION__, 'ContactTest.php', $description, '');
373 $this->assertEquals('Label1', $result['values'][1]);
374 }
375
376 ///////////////// civicrm_custom_field_delete methods
377
378 /**
379 * Check with no array.
380 */
381 public function testCustomFieldDeleteNoArray() {
382 $params = NULL;
383 $customField = $this->callAPIFailure('custom_field', 'delete', $params);
384 $this->assertEquals($customField['error_message'], 'Input variable `params` is not an array');
385 }
386
387 /**
388 * Check without Field ID.
389 */
390 public function testCustomFieldDeleteWithoutFieldID() {
391 $params = array();
392 $customField = $this->callAPIFailure('custom_field', 'delete', $params,
393 'Mandatory key(s) missing from params array: id');
394 }
395
396 /**
397 * Check without valid array.
398 */
399 public function testCustomFieldDelete() {
400 $customGroup = $this->customGroupCreate(array('extends' => 'Individual', 'title' => 'test_group'));
401 $customField = $this->customFieldCreate(array('custom_group_id' => $customGroup['id']));
402 $this->assertNotNull($customField['id']);
403
404 $params = array(
405 'id' => $customField['id'],
406 );
407 $result = $this->callAPIAndDocument('custom_field', 'delete', $params, __FUNCTION__, __FILE__);
408
409 $this->assertAPISuccess($result);
410 }
411
412 /**
413 * Check for Option Value.
414 */
415 public function testCustomFieldOptionValueDelete() {
416 $customGroup = $this->customGroupCreate(array('extends' => 'Contact', 'title' => 'ABC'));
417 $customOptionValueFields = $this->customFieldOptionValueCreate($customGroup, 'fieldABC');
418 $params = array(
419 'id' => $customOptionValueFields,
420 );
421
422 $customField = $this->callAPISuccess('custom_field', 'delete', $customOptionValueFields);
423 }
424
425 /**
426 * If there's one custom group for "Contact" and one for "Activity", then "Contact.getfields"
427 * and "Activity.getfields" should return only their respective fields (not the other's fields),
428 * and unrelated entities should return no custom fields.
429 */
430 public function testGetfields_CrossEntityPollution() {
431 $auxEntities = array('Email', 'Address', 'LocBlock', 'Membership', 'ContributionPage', 'ReportInstance');
432 $allEntities = array_merge(array('Contact', 'Activity'), $auxEntities);
433
434 // Baseline - getfields doesn't reporting any customfields for any entities
435 foreach ($allEntities as $entity) {
436 $this->assertEquals(
437 array(),
438 $this->getCustomFieldKeys($this->callAPISuccess($entity, 'getfields', array())),
439 "Baseline custom fields for $entity should be empty"
440 );
441 }
442
443 // Add some fields
444 $contactGroup = $this->customGroupCreate(array('extends' => 'Contact', 'title' => 'test_group_c'));
445 $contactField = $this->customFieldCreate(array(
446 'custom_group_id' => $contactGroup['id'],
447 'label' => 'For Contacts',
448 ));
449 $indivGroup = $this->customGroupCreate(array('extends' => 'Individual', 'title' => 'test_group_i'));
450 $indivField = $this->customFieldCreate(array('custom_group_id' => $indivGroup['id'], 'label' => 'For Individuals'));
451 $activityGroup = $this->customGroupCreate(array('extends' => 'Activity', 'title' => 'test_group_a'));
452 $activityField = $this->customFieldCreate(array(
453 'custom_group_id' => $activityGroup['id'],
454 'label' => 'For Activities',
455 ));
456
457 // Check getfields
458 $this->assertEquals(
459 array('custom_' . $contactField['id'], 'custom_' . $indivField['id']),
460 $this->getCustomFieldKeys($this->callAPISuccess('Contact', 'getfields', array())),
461 'Contact custom fields'
462 );
463 $this->assertEquals(
464 array('custom_' . $contactField['id'], 'custom_' . $indivField['id']),
465 $this->getCustomFieldKeys($this->callAPISuccess('Individual', 'getfields', array())),
466 'Individual custom fields'
467 );
468 $this->assertEquals(
469 array('custom_' . $contactField['id']),
470 $this->getCustomFieldKeys($this->callAPISuccess('Organization', 'getfields', array())),
471 'Organization custom fields'
472 );
473 $this->assertEquals(
474 array('custom_' . $activityField['id']),
475 $this->getCustomFieldKeys($this->callAPISuccess('Activity', 'getfields', array())),
476 'Activity custom fields'
477 );
478 foreach ($auxEntities as $entity) {
479 $this->assertEquals(
480 array(),
481 $this->getCustomFieldKeys($this->callAPISuccess($entity, 'getfields', array())),
482 "Custom fields for $entity should be empty"
483 );
484 }
485 }
486
487 /**
488 * Test setting and getting a custom file field value.
489 *
490 * Uses the "attachment" api for setting value.
491 */
492 public function testCustomFileField() {
493 $customGroup = $this->customGroupCreate(array('title' => 'attachment_test_group'));
494 $params = array(
495 'custom_group_id' => $customGroup['id'],
496 'name' => 'test_file_attachment',
497 'label' => 'test_file_attachment',
498 'html_type' => 'File',
499 'data_type' => 'File',
500 'is_active' => 1,
501 );
502 $customField = $this->callAPISuccess('custom_field', 'create', $params);
503 $cfId = 'custom_' . $customField['id'];
504
505 $cid = $this->individualCreate();
506
507 $attachment = $this->callAPISuccess('attachment', 'create', array(
508 'name' => CRM_Utils_String::createRandom(5, CRM_Utils_String::ALPHANUMERIC) . '_testCustomFileField.txt',
509 'mime_type' => 'text/plain',
510 'content' => 'My test content',
511 'field_name' => $cfId,
512 'entity_id' => $cid,
513 ));
514 $this->assertAttachmentExistence(TRUE, $attachment);
515
516 $result = $this->callAPISuccess('contact', 'getsingle', array(
517 'id' => $cid,
518 'return' => $cfId,
519 ));
520
521 $this->assertEquals($attachment['id'], $result[$cfId]);
522 }
523
524 /**
525 * @param $getFieldsResult
526 *
527 * @return array
528 */
529 public function getCustomFieldKeys($getFieldsResult) {
530 $isCustom = function ($key) {
531 return preg_match('/^custom_/', $key);
532 };
533 $r = array_values(array_filter(array_keys($getFieldsResult['values']), $isCustom));
534 sort($r);
535 return $r;
536 }
537
538 }