3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
12 use Civi\Api4\CustomGroup
;
13 use Civi\Api4\CustomField
;
14 use Civi\Api4\OptionValue
;
17 * Trait Custom Data trait.
19 * Trait for setting up custom data in tests.
21 trait CRMTraits_Custom_CustomDataTrait
{
24 * Create a custom group with fields of multiple types.
26 * @param array $groupParams
28 * @throws \API_Exception
29 * @throws \Civi\API\Exception\UnauthorizedException
31 public function createCustomGroupWithFieldsOfAllTypes($groupParams = []) {
32 $this->createCustomGroup($groupParams);
33 $this->ids
['CustomField'] = $this->createCustomFieldsOfAllTypes();
37 * Create a custom group.
39 * @param array $params
43 * @throws \API_Exception
44 * @throws \Civi\API\Exception\UnauthorizedException
46 public function createCustomGroup($params = []) {
47 $params = array_merge([
48 'title' => 'Custom Group',
49 'extends' => $this->entity ??
'Contact',
54 $identifier = $params['name'] ??
$params['title'];
56 $this->ids
['CustomGroup'][$identifier] = CustomGroup
::create(FALSE)
61 catch (API_Exception
$e) {
62 $this->fail('Could not create group ' . $e->getMessage());
64 return $this->ids
['CustomGroup'][$identifier];
68 * Get the table_name for the specified custom group.
70 * @param string $identifier
74 public function getCustomGroupTable($identifier = 'Custom Group') {
75 return $this->callAPISuccessGetValue('CustomGroup', ['id' => $this->ids
['CustomGroup'][$identifier], 'return' => 'table_name']);
79 * Get the the column name for the identified custom field.
82 * Identifier - generally keys map to data type - eg. 'text', 'int' etc.
86 protected function getCustomFieldColumnName($key) {
87 return $this->callAPISuccessGetValue('CustomField', ['id' => $this->getCustomFieldID($key), 'return' => 'column_name']);
91 * Create a custom group with a single field.
93 * @param array $groupParams
94 * Params for the group to be created.
95 * @param string $customFieldType
97 * @param string|null $identifier
99 * @param array $fieldParams
102 public function createCustomGroupWithFieldOfType(array $groupParams = [], string $customFieldType = 'text', ?
string $identifier = NULL, array $fieldParams = []): void
{
103 $supported = ['text', 'select', 'date', 'checkbox', 'int', 'contact_reference', 'radio', 'multi_country'];
104 if (!in_array($customFieldType, $supported, TRUE)) {
105 $this->fail('we have not yet extracted other custom field types from createCustomFieldsOfAllTypes, Use consistent syntax when you do');
107 $groupParams['title'] = empty($groupParams['title']) ?
$identifier . 'Group with field ' . $customFieldType : $groupParams['title'];
108 $groupParams['name'] = $identifier ??
'Custom Group';
109 $this->createCustomGroup($groupParams);
110 $reference = &$this->ids
['CustomField'][$identifier . $customFieldType];
111 $fieldParams = array_merge($fieldParams, ['custom_group_id' => $this->ids
['CustomGroup'][$groupParams['name']]]);
112 switch ($customFieldType) {
114 $reference = $this->createTextCustomField($fieldParams)['id'];
118 $reference = $this->createSelectCustomField($fieldParams)['id'];
122 $reference = $this->createStringCheckboxCustomField($fieldParams)['id'];
126 $reference = $this->createIntCustomField($fieldParams)['id'];
130 $reference = $this->createDateCustomField($fieldParams)['id'];
133 case 'contact_reference':
134 $reference = $this->createContactReferenceCustomField($fieldParams)['id'];
138 $reference = $this->createIntegerRadioCustomField($fieldParams)['id'];
141 case 'multi_country':
142 $reference = $this->createMultiCountryCustomField($fieldParams)['id'];
151 public function createCustomFieldsOfAllTypes() {
152 $customGroupID = $this->ids
['CustomGroup']['Custom Group'];
154 $ids['text'] = (int) $this->createTextCustomField(['custom_group_id' => $customGroupID])['id'];
155 $ids['select_string'] = (int) $this->createSelectCustomField(['custom_group_id' => $customGroupID])['id'];
156 $ids['select_date'] = (int) $this->createDateCustomField(['custom_group_id' => $customGroupID])['id'];
157 $ids['int'] = (int) $this->createIntCustomField(['custom_group_id' => $customGroupID])['id'];
158 $ids['link'] = (int) $this->createLinkCustomField(['custom_group_id' => $customGroupID])['id'];
159 $ids['file'] = (int) $this->createFileCustomField(['custom_group_id' => $customGroupID])['id'];
160 $ids['country'] = (int) $this->createCountryCustomField(['custom_group_id' => $customGroupID])['id'];
161 $ids['multi_country'] = (int) $this->createMultiCountryCustomField(['custom_group_id' => $customGroupID])['id'];
162 $ids['contact_reference'] = $this->createContactReferenceCustomField(['custom_group_id' => $customGroupID])['id'];
163 $ids['state'] = (int) $this->createStateCustomField(['custom_group_id' => $customGroupID])['id'];
164 $ids['multi_state'] = (int) $this->createMultiStateCustomField(['custom_group_id' => $customGroupID])['id'];
165 $ids['boolean'] = (int) $this->createBooleanCustomField(['custom_group_id' => $customGroupID])['id'];
166 $ids['checkbox'] = (int) $this->createStringCheckboxCustomField(['custom_group_id' => $customGroupID])['id'];
171 * Get the custom field name for the relevant key.
173 * e.g returns 'custom_5' where 5 is the id of the field using the key.
175 * Generally keys map to data types.
181 protected function getCustomFieldName($key) {
182 return 'custom_' . $this->getCustomFieldID($key);
186 * Add another option to the custom field.
189 * @param array $values
192 * @throws \API_Exception
194 protected function addOptionToCustomField($key, $values) {
195 $optionGroupID = CustomField
::get(FALSE)
196 ->addWhere('id', '=', $this->getCustomFieldID($key))
197 ->addSelect('option_group_id')
198 ->execute()->first()['option_group_id'];
199 return (int) OptionValue
::create(FALSE)
200 ->setValues(array_merge(['option_group_id' => $optionGroupID], $values))
201 ->execute()->first()['value'];
205 * Get the custom field name for the relevant key.
207 * e.g returns 'custom_5' where 5 is the id of the field using the key.
209 * Generally keys map to data types.
215 protected function getCustomFieldID($key) {
216 return $this->ids
['CustomField'][$key];
220 * Get the option group id of the created field.
226 protected function getOptionGroupID(string $key): string {
227 return (string) $this->callAPISuccessGetValue('CustomField', [
228 'id' => $this->getCustomFieldID($key),
229 'return' => 'option_group_id',
234 * Get the option group id of the created field.
240 protected function getOptionGroupName(string $key): string {
241 return (string) $this->callAPISuccessGetValue('CustomField', [
242 'id' => $this->getCustomFieldID($key),
243 'return' => 'option_group_id.name',
248 * Create a custom text fields.
250 * @param array $params
251 * Parameter overrides, must include custom_group_id.
255 protected function createIntCustomField($params = []) {
256 $params = array_merge($this->getFieldsValuesByType('Int'), $params);
257 return $this->callAPISuccess('CustomField', 'create', $params)['values'][0];
261 * Create a custom text fields.
263 * @param array $params
264 * Parameter overrides, must include custom_group_id.
268 protected function createBooleanCustomField($params = []) {
269 $params = array_merge($this->getFieldsValuesByType('Boolean'), $params);
270 return $this->callAPISuccess('CustomField', 'create', $params)['values'][0];
274 * Create a custom text fields.
276 * @param array $params
277 * Parameter overrides, must include custom_group_id.
281 protected function createContactReferenceCustomField($params = []) {
282 $params = array_merge($this->getFieldsValuesByType('ContactReference'), $params);
283 return $this->callAPISuccess('custom_field', 'create', $params)['values'][0];
287 * Create a custom text fields.
289 * @param array $params
290 * Parameter overrides, must include custom_group_id.
294 protected function createTextCustomField($params = []) {
295 $params = array_merge($this->getFieldsValuesByType('String'), $params);
296 return $this->callAPISuccess('custom_field', 'create', $params)['values'][0];
300 * Create a custom text fields.
302 * @param array $params
303 * Parameter overrides, must include custom_group_id.
307 protected function createLinkCustomField($params = []) {
308 $params = array_merge($this->getFieldsValuesByType('Link'), $params);
309 return $this->callAPISuccess('custom_field', 'create', $params)['values'][0];
313 * Create a custom country fields.
315 * @param array $params
316 * Parameter overrides, must include custom_group_id.
320 protected function createCountryCustomField($params = []) {
321 $params = array_merge($this->getFieldsValuesByType('Country'), $params);
322 return $this->callAPISuccess('custom_field', 'create', $params)['values'][0];
326 * Create a custom multi select country fields.
328 * @param array $params
329 * Parameter overrides, must include custom_group_id.
333 protected function createMultiCountryCustomField($params = []) {
334 $params = array_merge($this->getFieldsValuesByType('Country', 'Multi-Select Country'), $params);
335 return $this->callAPISuccess('custom_field', 'create', $params)['values'][0];
339 * Create a custom state fields.
341 * @param array $params
342 * Parameter overrides, must include custom_group_id.
346 protected function createStateCustomField($params = []) {
347 $params = array_merge($this->getFieldsValuesByType('StateProvince'), $params);
348 return $this->callAPISuccess('custom_field', 'create', $params)['values'][0];
352 * Create a custom multi select state fields.
354 * @param array $params
355 * Parameter overrides, must include custom_group_id.
359 protected function createMultiStateCustomField($params = []) {
360 $params = array_merge($this->getFieldsValuesByType('StateProvince', 'Multi-Select State/Province'), $params);
361 return $this->callAPISuccess('custom_field', 'create', $params)['values'][0];
365 * Create a custom text fields.
367 * @param array $params
368 * Parameter overrides, must include custom_group_id.
372 protected function createFileCustomField($params = []) {
373 $params = array_merge($this->getFieldsValuesByType('File'), $params);
374 return $this->callAPISuccess('custom_field', 'create', $params)['values'][0];
378 * Create custom select field.
380 * @param array $params
381 * Parameter overrides, must include custom_group_id.
385 protected function createSelectCustomField(array $params): array {
386 $params = array_merge($this->getFieldsValuesByType('String', 'Select'), $params);
387 return $this->callAPISuccess('custom_field', 'create', $params)['values'][0];
391 * Create custom select field.
393 * @param array $params
394 * Parameter overrides, must include custom_group_id.
398 protected function createAutoCompleteCustomField(array $params): array {
399 $params = array_merge($this->getFieldsValuesByType('String', 'Autocomplete-Select'), $params);
400 return $this->callAPISuccess('custom_field', 'create', $params)['values'][0];
404 * Create a custom field of type date.
406 * @param array $params
410 protected function createDateCustomField($params): array {
411 $params = array_merge($this->getFieldsValuesByType('Date'), $params);
412 return $this->callAPISuccess('custom_field', 'create', $params)['values'][0];
416 * Create a custom field of type radio with integer values.
418 * @param array $params
422 protected function createStringCheckboxCustomField(array $params): array {
423 $params = array_merge($this->getFieldsValuesByType('String', 'CheckBox'), $params);
424 return $this->callAPISuccess('custom_field', 'create', $params)['values'][0];
428 * Create a custom field of type radio with integer values.
430 * @param array $params
434 protected function createIntegerRadioCustomField($params): array {
435 $params = array_merge($this->getFieldsValuesByType('Int', 'Radio'), $params);
436 return $this->callAPISuccess('custom_field', 'create', $params)['values'][0];
440 * Get default field values for the type of field.
443 * @param string $htmlType
447 public function getFieldsValuesByType($dataType, $htmlType = 'default') {
448 $values = $this->getAvailableFieldCombinations()[$dataType];
450 'is_searchable' => 1,
452 'default_value' => '',
454 ], array_merge($values['default'], $values[$htmlType])
459 * Get data available for custom fields.
461 * The 'default' key holds general values. Where more than one html type is an option
462 * then the any values that differ to the defaults are keyed by html key.
464 * The order below is consistent with the UI.
468 protected function getAvailableFieldCombinations() {
472 'label' => 'Enter text here',
473 'html_type' => 'Text',
474 'data_type' => 'String',
475 'default_value' => 'xyz',
476 'text_length' => 300,
479 'label' => 'Pick Color',
480 'html_type' => 'Select',
481 'data_type' => 'String',
483 'default_value' => '',
506 'label' => 'Pick Color',
507 'html_type' => 'Radio',
508 'data_type' => 'String',
510 'default_value' => '',
533 'label' => 'Pick Shade',
534 'html_type' => 'CheckBox',
535 'data_type' => 'String',
537 'default_value' => '',
566 'label' => 'Pick Color',
567 'html_type' => 'Multi-Select',
568 'data_type' => 'String',
570 'default_value' => '',
592 'Autocomplete-Select' => [
593 'label' => 'Pick Color',
594 'html_type' => 'Autocomplete-Select',
595 'data_type' => 'String',
597 'default_value' => '',
622 'label' => 'Enter integer here',
623 'html_type' => 'Text',
624 'data_type' => 'Int',
625 'default_value' => '4',
626 'is_search_range' => 1,
629 'label' => 'Integer select',
630 'html_type' => 'Select',
647 'label' => 'Integer radio',
648 'html_type' => 'Radio',
663 'label' => 'Red Testing',
673 'name' => 'test_date',
674 'label' => 'Test Date',
675 'html_type' => 'Select Date',
676 'data_type' => 'Date',
677 'default_value' => '20090711',
679 'is_search_range' => 1,
686 'html_type' => 'Text',
687 'data_type' => 'Float',
690 'label' => 'Number select',
691 'html_type' => 'Select',
708 'label' => 'Number radio',
709 'html_type' => 'Radio',
729 'html_type' => 'Text',
730 'data_type' => 'Money',
733 'label' => 'Money select',
734 'html_type' => 'Select',
751 'label' => 'Money radio',
752 'html_type' => 'Radio',
772 'html_type' => 'TextArea',
773 'data_type' => 'Memo',
774 'attributes' => 'rows=4, cols=60',
776 'RichTextEditor' => [
777 'label' => 'Memo Rich Text Editor',
778 'html_type' => 'Memo',
783 'data_type' => 'Boolean',
784 'html_type' => 'Radio',
790 'data_type' => 'StateProvince',
791 'html_type' => 'Select State/Province',
795 'Multi-Select State/Province' => [
796 'html_type' => 'Multi-Select State/Province',
797 'label' => 'State-multi',
802 'data_type' => 'Country',
803 'html_type' => 'Select Country',
804 'label' => 'Country',
807 'Multi-Select Country' => [
808 'html_type' => 'Multi-Select Country',
809 'label' => 'Country-multi',
815 'label' => 'My file',
816 'data_type' => 'File',
817 'html_type' => 'File',
822 'name' => 'test_link',
823 'label' => 'test_link',
824 'html_type' => 'Link',
825 'data_type' => 'Link',
826 'default_value' => 'http://civicrm.org',
829 'ContactReference' => [
831 'label' => 'Contact reference field',
832 'html_type' => 'Autocomplete-Select',
833 'data_type' => 'ContactReference',