Core.setting.php - Tweak prose for defaultExternUrl, again
[civicrm-core.git] / Civi / Api4 / Service / Spec / SpecFormatter.php
1 <?php
2
3 /*
4 +--------------------------------------------------------------------+
5 | Copyright CiviCRM LLC. All rights reserved. |
6 | |
7 | This work is published under the GNU AGPLv3 license with some |
8 | permitted exceptions and without any warranty. For full license |
9 | and copyright information, see https://civicrm.org/licensing |
10 +--------------------------------------------------------------------+
11 */
12
13 /**
14 *
15 * @package CRM
16 * @copyright CiviCRM LLC https://civicrm.org/licensing
17 */
18
19
20 namespace Civi\Api4\Service\Spec;
21
22 use CRM_Core_DAO_AllCoreTables as AllCoreTables;
23
24 class SpecFormatter {
25
26 /**
27 * @param FieldSpec[] $fields
28 * @param bool $includeFieldOptions
29 * @param array $values
30 *
31 * @return array
32 */
33 public static function specToArray($fields, $includeFieldOptions = FALSE, $values = []) {
34 $fieldArray = [];
35
36 foreach ($fields as $field) {
37 if ($includeFieldOptions) {
38 $field->getOptions($values, $includeFieldOptions);
39 }
40 $fieldArray[$field->getName()] = $field->toArray();
41 }
42
43 return $fieldArray;
44 }
45
46 /**
47 * @param array $data
48 * @param string $entity
49 *
50 * @return FieldSpec
51 */
52 public static function arrayToField(array $data, $entity) {
53 $dataTypeName = self::getDataType($data);
54
55 if (!empty($data['custom_group_id'])) {
56 $field = new CustomFieldSpec($data['name'], $entity, $dataTypeName);
57 if (strpos($entity, 'Custom_') !== 0) {
58 $field->setName($data['custom_group.name'] . '.' . $data['name']);
59 }
60 else {
61 $field->setCustomTableName($data['custom_group.table_name']);
62 }
63 $field->setColumnName($data['column_name']);
64 $field->setCustomFieldId($data['id'] ?? NULL);
65 $field->setCustomGroupName($data['custom_group.name']);
66 $field->setTitle($data['label'] ?? NULL);
67 $field->setHelpPre($data['help_pre'] ?? NULL);
68 $field->setHelpPost($data['help_post'] ?? NULL);
69 $field->setOptions(self::customFieldHasOptions($data));
70 if (\CRM_Core_BAO_CustomField::isSerialized($data)) {
71 $field->setSerialize(\CRM_Core_DAO::SERIALIZE_SEPARATOR_BOOKEND);
72 }
73 }
74 else {
75 $name = $data['name'] ?? NULL;
76 $field = new FieldSpec($name, $entity, $dataTypeName);
77 $field->setRequired(!empty($data['required']));
78 $field->setTitle($data['title'] ?? NULL);
79 $field->setOptions(!empty($data['pseudoconstant']));
80 $field->setSerialize($data['serialize'] ?? NULL);
81 }
82
83 $field->setDefaultValue($data['default'] ?? NULL);
84 $field->setDescription($data['description'] ?? NULL);
85 self::setInputTypeAndAttrs($field, $data, $dataTypeName);
86
87 $field->setPermission($data['permission'] ?? NULL);
88 $fkAPIName = $data['FKApiName'] ?? NULL;
89 $fkClassName = $data['FKClassName'] ?? NULL;
90 if ($fkAPIName || $fkClassName) {
91 $field->setFkEntity($fkAPIName ?: AllCoreTables::getBriefName($fkClassName));
92 }
93
94 return $field;
95 }
96
97 /**
98 * Does this custom field have options
99 *
100 * @param array $field
101 * @return bool
102 */
103 private static function customFieldHasOptions($field) {
104 // This will include boolean fields with Yes/No options.
105 if (in_array($field['html_type'], ['Radio', 'CheckBox'])) {
106 return TRUE;
107 }
108 // Do this before the "Select" string search because date fields have a "Select Date" html_type
109 // and contactRef fields have an "Autocomplete-Select" html_type - contacts are an FK not an option list.
110 if (in_array($field['data_type'], ['ContactReference', 'Date'])) {
111 return FALSE;
112 }
113 if (strpos($field['html_type'], 'Select') !== FALSE) {
114 return TRUE;
115 }
116 return !empty($field['option_group_id']);
117 }
118
119 /**
120 * Get the data type from an array. Defaults to 'data_type' with fallback to
121 * mapping for the integer value 'type'
122 *
123 * @param array $data
124 *
125 * @return string
126 */
127 private static function getDataType(array $data) {
128 if (isset($data['data_type'])) {
129 return !empty($data['time_format']) ? 'Timestamp' : $data['data_type'];
130 }
131
132 $dataTypeInt = $data['type'] ?? NULL;
133 $dataTypeName = \CRM_Utils_Type::typeToString($dataTypeInt);
134
135 return $dataTypeName;
136 }
137
138 /**
139 * @param \Civi\Api4\Service\Spec\FieldSpec $fieldSpec
140 * @param array $data
141 * @param string $dataTypeName
142 */
143 public static function setInputTypeAndAttrs(FieldSpec &$fieldSpec, $data, $dataTypeName) {
144 $inputType = $data['html']['type'] ?? $data['html_type'] ?? NULL;
145 $inputAttrs = $data['html'] ?? [];
146 unset($inputAttrs['type']);
147
148 if (strstr($inputType, 'Multi-Select') || ($inputType == 'Select' && !empty($data['serialize']))) {
149 $inputAttrs['multiple'] = TRUE;
150 $inputType = 'Select';
151 }
152 $map = [
153 'Select State/Province' => 'Select',
154 'Select Country' => 'Select',
155 'Select Date' => 'Date',
156 'Link' => 'Url',
157 ];
158 $inputType = $map[$inputType] ?? $inputType;
159 if ($inputType == 'Date' && !empty($inputAttrs['formatType'])) {
160 self::setLegacyDateFormat($inputAttrs);
161 }
162 // Date/time settings from custom fields
163 if ($inputType == 'Date' && !empty($data['custom_group_id'])) {
164 $inputAttrs['time'] = empty($data['time_format']) ? FALSE : ($data['time_format'] == 1 ? 12 : 24);
165 $inputAttrs['date'] = $data['date_format'];
166 $inputAttrs['start_date_years'] = (int) $data['start_date_years'];
167 $inputAttrs['end_date_years'] = (int) $data['end_date_years'];
168 }
169 if ($inputType == 'Text' && !empty($data['maxlength'])) {
170 $inputAttrs['maxlength'] = (int) $data['maxlength'];
171 }
172 if ($inputType == 'TextArea') {
173 foreach (['rows', 'cols', 'note_rows', 'note_cols'] as $prop) {
174 if (!empty($data[$prop])) {
175 $inputAttrs[str_replace('note_', '', $prop)] = (int) $data[$prop];
176 }
177 }
178 }
179 $fieldSpec
180 ->setInputType($inputType)
181 ->setInputAttrs($inputAttrs);
182 }
183
184 /**
185 * @param array $inputAttrs
186 */
187 private static function setLegacyDateFormat(&$inputAttrs) {
188 if (empty(\Civi::$statics['legacyDatePrefs'][$inputAttrs['formatType']])) {
189 \Civi::$statics['legacyDatePrefs'][$inputAttrs['formatType']] = [];
190 $params = ['name' => $inputAttrs['formatType']];
191 \CRM_Core_DAO::commonRetrieve('CRM_Core_DAO_PreferencesDate', $params, \Civi::$statics['legacyDatePrefs'][$inputAttrs['formatType']]);
192 }
193 $dateFormat = \Civi::$statics['legacyDatePrefs'][$inputAttrs['formatType']];
194 unset($inputAttrs['formatType']);
195 $inputAttrs['time'] = !empty($dateFormat['time_format']);
196 $inputAttrs['date'] = TRUE;
197 $inputAttrs['start_date_years'] = (int) $dateFormat['start'];
198 $inputAttrs['end_date_years'] = (int) $dateFormat['end'];
199 }
200
201 }