Commit | Line | Data |
---|---|---|
19b53e5b C |
1 | <?php |
2 | ||
380f3545 TO |
3 | /* |
4 | +--------------------------------------------------------------------+ | |
41498ac5 | 5 | | Copyright CiviCRM LLC. All rights reserved. | |
380f3545 | 6 | | | |
41498ac5 TO |
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 | | |
380f3545 TO |
10 | +--------------------------------------------------------------------+ |
11 | */ | |
12 | ||
13 | /** | |
14 | * | |
15 | * @package CRM | |
ca5cec67 | 16 | * @copyright CiviCRM LLC https://civicrm.org/licensing |
380f3545 TO |
17 | * $Id$ |
18 | * | |
19 | */ | |
20 | ||
21 | ||
19b53e5b C |
22 | namespace Civi\Api4\Utils; |
23 | ||
19b53e5b C |
24 | require_once 'api/v3/utils.php'; |
25 | ||
26 | class FormattingUtil { | |
27 | ||
28 | /** | |
29 | * Massage values into the format the BAO expects for a write operation | |
30 | * | |
31 | * @param $params | |
32 | * @param $entity | |
33 | * @param $fields | |
34 | * @throws \API_Exception | |
35 | */ | |
36 | public static function formatWriteParams(&$params, $entity, $fields) { | |
37 | foreach ($fields as $name => $field) { | |
38 | if (!empty($params[$name])) { | |
39 | $value =& $params[$name]; | |
40 | // Hack for null values -- see comment below | |
41 | if ($value === 'null') { | |
42 | $value = 'Null'; | |
43 | } | |
2929a8fb | 44 | self::formatInputValue($value, $field, $entity); |
19b53e5b C |
45 | // Ensure we have an array for serialized fields |
46 | if (!empty($field['serialize'] && !is_array($value))) { | |
47 | $value = (array) $value; | |
48 | } | |
49 | } | |
50 | /* | |
51 | * Because of the wacky way that database values are saved we need to format | |
52 | * some of the values here. In this strange world the string 'null' is used to | |
53 | * unset values. Hence if we encounter true null we change it to string 'null'. | |
54 | * | |
55 | * If we encounter the string 'null' then we assume the user actually wants to | |
56 | * set the value to string null. However since the string null is reserved for | |
57 | * unsetting values we must change it. Another quirk of the DB_DataObject is | |
58 | * that it allows 'Null' to be set, but any other variation of string 'null' | |
59 | * will be converted to true null, e.g. 'nuLL', 'NUlL' etc. so we change it to | |
60 | * 'Null'. | |
61 | */ | |
62 | elseif (array_key_exists($name, $params) && $params[$name] === NULL) { | |
63 | $params[$name] = 'null'; | |
64 | } | |
65 | } | |
c9b7a552 TO |
66 | |
67 | \CRM_Utils_API_HTMLInputCoder::singleton()->encodeRow($params); | |
19b53e5b C |
68 | } |
69 | ||
70 | /** | |
71 | * Transform raw api input to appropriate format for use in a SQL query. | |
72 | * | |
73 | * This is used by read AND write actions (Get, Create, Update, Replace) | |
74 | * | |
75 | * @param $value | |
76 | * @param $fieldSpec | |
77 | * @param string $entity | |
78 | * Ex: 'Contact', 'Domain' | |
79 | * @throws \API_Exception | |
80 | */ | |
2929a8fb | 81 | public static function formatInputValue(&$value, $fieldSpec, $entity) { |
19b53e5b C |
82 | if (is_array($value)) { |
83 | foreach ($value as &$val) { | |
2929a8fb | 84 | self::formatInputValue($val, $fieldSpec, $entity); |
19b53e5b C |
85 | } |
86 | return; | |
87 | } | |
2929a8fb | 88 | $fk = $fieldSpec['name'] == 'id' ? $entity : $fieldSpec['fk_entity'] ?? NULL; |
19b53e5b C |
89 | |
90 | if ($fk === 'Domain' && $value === 'current_domain') { | |
91 | $value = \CRM_Core_Config::domainID(); | |
92 | } | |
93 | ||
94 | if ($fk === 'Contact' && !is_numeric($value)) { | |
95 | $value = \_civicrm_api3_resolve_contactID($value); | |
96 | if ('unknown-user' === $value) { | |
97 | throw new \API_Exception("\"{$fieldSpec['name']}\" \"{$value}\" cannot be resolved to a contact ID", 2002, ['error_field' => $fieldSpec['name'], "type" => "integer"]); | |
98 | } | |
99 | } | |
100 | ||
2929a8fb | 101 | switch ($fieldSpec['data_type'] ?? NULL) { |
19b53e5b C |
102 | case 'Timestamp': |
103 | $value = date('Y-m-d H:i:s', strtotime($value)); | |
104 | break; | |
105 | ||
106 | case 'Date': | |
107 | $value = date('Ymd', strtotime($value)); | |
108 | break; | |
109 | } | |
c9b7a552 TO |
110 | |
111 | $hic = \CRM_Utils_API_HTMLInputCoder::singleton(); | |
112 | if (!$hic->isSkippedField($fieldSpec['name'])) { | |
113 | $value = $hic->encodeValue($value); | |
114 | } | |
19b53e5b C |
115 | } |
116 | ||
2929a8fb CW |
117 | /** |
118 | * Unserialize raw DAO values and convert to correct type | |
119 | * | |
120 | * @param array $results | |
121 | * @param array $fields | |
122 | * @param string $entity | |
123 | * @throws \CRM_Core_Exception | |
124 | */ | |
125 | public static function formatOutputValues(&$results, $fields, $entity) { | |
126 | foreach ($results as &$result) { | |
127 | // Remove inapplicable contact fields | |
128 | if ($entity === 'Contact' && !empty($result['contact_type'])) { | |
129 | \CRM_Utils_Array::remove($result, self::contactFieldsToRemove($result['contact_type'])); | |
130 | } | |
131 | foreach ($result as $field => $value) { | |
132 | $dataType = $fields[$field]['data_type'] ?? ($field == 'id' ? 'Integer' : NULL); | |
133 | if (!empty($fields[$field]['serialize'])) { | |
134 | if (is_string($value)) { | |
135 | $result[$field] = $value = \CRM_Core_DAO::unSerializeField($value, $fields[$field]['serialize']); | |
136 | foreach ($value as $key => $val) { | |
137 | $result[$field][$key] = self::convertDataType($val, $dataType); | |
138 | } | |
139 | } | |
140 | } | |
141 | else { | |
142 | $result[$field] = self::convertDataType($value, $dataType); | |
143 | } | |
144 | } | |
145 | } | |
146 | } | |
147 | ||
148 | /** | |
149 | * @param mixed $value | |
150 | * @param string $dataType | |
151 | * @return mixed | |
152 | */ | |
153 | public static function convertDataType($value, $dataType) { | |
154 | if (isset($value)) { | |
155 | switch ($dataType) { | |
156 | case 'Boolean': | |
157 | return (bool) $value; | |
158 | ||
159 | case 'Integer': | |
160 | return (int) $value; | |
161 | ||
162 | case 'Money': | |
163 | case 'Float': | |
164 | return (float) $value; | |
165 | } | |
166 | } | |
167 | return $value; | |
168 | } | |
169 | ||
170 | /** | |
171 | * @param string $contactType | |
172 | * @return array | |
173 | */ | |
174 | public static function contactFieldsToRemove($contactType) { | |
175 | if (!isset(\Civi::$statics[__CLASS__][__FUNCTION__][$contactType])) { | |
176 | \Civi::$statics[__CLASS__][__FUNCTION__][$contactType] = []; | |
177 | foreach (\CRM_Contact_DAO_Contact::fields() as $field) { | |
178 | if (!empty($field['contactType']) && $field['contactType'] != $contactType) { | |
179 | \Civi::$statics[__CLASS__][__FUNCTION__][$contactType][] = $field['name']; | |
180 | } | |
181 | } | |
182 | } | |
183 | return \Civi::$statics[__CLASS__][__FUNCTION__][$contactType]; | |
184 | } | |
185 | ||
19b53e5b | 186 | } |