Merge pull request #17253 from mattwire/utf8convertblocksize
[civicrm-core.git] / CRM / Core / BAO / CustomOption.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
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 +--------------------------------------------------------------------+
10 */
11
12 /**
13 *
14 * @package CRM
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
16 */
17
18 /**
19 * Business objects for managing custom data options.
20 *
21 */
22 class CRM_Core_BAO_CustomOption {
23
24 /**
25 * Fetch object based on array of properties.
26 *
27 * @param array $params
28 * (reference ) an assoc array of name/value pairs.
29 * @param array $defaults
30 * (reference ) an assoc array to hold the flattened values.
31 *
32 * @return CRM_Core_BAO_CustomOption
33 */
34 public static function retrieve(&$params, &$defaults) {
35 $customOption = new CRM_Core_DAO_OptionValue();
36 $customOption->copyValues($params);
37 if ($customOption->find(TRUE)) {
38 CRM_Core_DAO::storeValues($customOption, $defaults);
39 return $customOption;
40 }
41 return NULL;
42 }
43
44 /**
45 * Returns all active options ordered by weight for a given field.
46 *
47 * @param int $fieldID
48 * Field whose options are needed.
49 * @param bool $inactiveNeeded Do we need inactive options ?.
50 * Do we need inactive options ?.
51 *
52 * @return array
53 * all active options for fieldId
54 */
55 public static function getCustomOption(
56 $fieldID,
57 $inactiveNeeded = FALSE
58 ) {
59 $options = [];
60 if (!$fieldID) {
61 return $options;
62 }
63
64 $optionValues = CRM_Core_PseudoConstant::get('CRM_Core_BAO_CustomField', 'custom_' . $fieldID, [], $inactiveNeeded ? 'get' : 'create');
65
66 foreach ((array) $optionValues as $value => $label) {
67 $options[] = [
68 'label' => $label,
69 'value' => $value,
70 ];
71 }
72
73 return $options;
74 }
75
76 /**
77 * Wrapper for ajax option selector.
78 *
79 * @param array $params
80 * Associated array for params record id.
81 *
82 * @return array
83 * associated array of option list
84 * -rp = rowcount
85 * -page= offset
86 */
87 public static function getOptionListSelector(&$params) {
88 $options = [];
89
90 $field = CRM_Core_BAO_CustomField::getFieldObject($params['fid']);
91 $defVal = CRM_Utils_Array::explodePadded($field->default_value);
92
93 // format the params
94 $params['offset'] = ($params['page'] - 1) * $params['rp'];
95 $params['rowCount'] = $params['rp'];
96
97 if (!$field->option_group_id) {
98 return $options;
99 }
100 $queryParams = [1 => [$field->option_group_id, 'Integer']];
101 $total = "SELECT COUNT(*) FROM civicrm_option_value WHERE option_group_id = %1";
102 $params['total'] = CRM_Core_DAO::singleValueQuery($total, $queryParams);
103
104 $limit = " LIMIT {$params['offset']}, {$params['rowCount']} ";
105 $orderBy = ' ORDER BY options.weight asc';
106
107 $query = "SELECT * FROM civicrm_option_value as options WHERE option_group_id = %1 {$orderBy} {$limit}";
108 $dao = CRM_Core_DAO::executeQuery($query, $queryParams);
109 $links = CRM_Custom_Page_Option::actionLinks();
110
111 $fields = ['id', 'label', 'value'];
112 $config = CRM_Core_Config::singleton();
113 while ($dao->fetch()) {
114 $options[$dao->id] = [];
115 foreach ($fields as $k) {
116 $options[$dao->id][$k] = $dao->$k;
117 }
118 $action = array_sum(array_keys($links));
119 $class = 'crm-entity';
120 // update enable/disable links depending on custom_field properties.
121 if ($dao->is_active) {
122 $action -= CRM_Core_Action::ENABLE;
123 }
124 else {
125 $class .= ' disabled';
126 $action -= CRM_Core_Action::DISABLE;
127 }
128
129 $isGroupLocked = (bool) CRM_Core_DAO::getFieldValue(
130 CRM_Core_DAO_OptionGroup::class,
131 $field->option_group_id,
132 'is_locked'
133 );
134
135 // disable deletion of option values for locked option groups
136 if (($action & CRM_Core_Action::DELETE) && $isGroupLocked) {
137 $action -= CRM_Core_Action::DELETE;
138 }
139
140 if (in_array($field->html_type, ['CheckBox', 'Multi-Select'])) {
141 $options[$dao->id]['is_default'] = (isset($defVal) && in_array($dao->value, $defVal));
142 }
143 else {
144 $options[$dao->id]['is_default'] = ($field->default_value == $dao->value);
145 }
146 $options[$dao->id]['description'] = $dao->description;
147 $options[$dao->id]['class'] = $dao->id . ',' . $class;
148 $options[$dao->id]['is_active'] = empty($dao->is_active) ? ts('No') : ts('Yes');
149 $options[$dao->id]['links'] = CRM_Core_Action::formLink($links,
150 $action,
151 [
152 'id' => $dao->id,
153 'fid' => $params['fid'],
154 'gid' => $params['gid'],
155 ],
156 ts('more'),
157 FALSE,
158 'customOption.row.actions',
159 'customOption',
160 $dao->id
161 );
162 }
163
164 return $options;
165 }
166
167 /**
168 * Delete Option.
169 *
170 * @param $optionId integer
171 * option id
172 *
173 */
174 public static function del($optionId) {
175 // get the customFieldID
176 $query = "
177 SELECT f.id as id, f.data_type as dataType
178 FROM civicrm_option_value v,
179 civicrm_option_group g,
180 civicrm_custom_field f
181 WHERE v.id = %1
182 AND g.id = f.option_group_id
183 AND g.id = v.option_group_id";
184 $params = [1 => [$optionId, 'Integer']];
185 $dao = CRM_Core_DAO::executeQuery($query, $params);
186 if ($dao->fetch()) {
187 if (in_array($dao->dataType,
188 ['Int', 'Float', 'Money', 'Boolean']
189 )) {
190 $value = 0;
191 }
192 else {
193 $value = '';
194 }
195 $params = [
196 'optionId' => $optionId,
197 'fieldId' => $dao->id,
198 'value' => $value,
199 ];
200 // delete this value from the tables
201 self::updateCustomValues($params);
202
203 // also delete this option value
204 $query = "
205 DELETE
206 FROM civicrm_option_value
207 WHERE id = %1";
208 $params = [1 => [$optionId, 'Integer']];
209 CRM_Core_DAO::executeQuery($query, $params);
210 }
211 }
212
213 /**
214 * @param array $params
215 *
216 * @throws Exception
217 */
218 public static function updateCustomValues($params) {
219 $optionDAO = new CRM_Core_DAO_OptionValue();
220 $optionDAO->id = $params['optionId'];
221 $optionDAO->find(TRUE);
222 $oldValue = $optionDAO->value;
223
224 // get the table, column, html_type and data type for this field
225 $query = "
226 SELECT g.table_name as tableName ,
227 f.column_name as columnName,
228 f.data_type as dataType,
229 f.html_type as htmlType
230 FROM civicrm_custom_group g,
231 civicrm_custom_field f
232 WHERE f.custom_group_id = g.id
233 AND f.id = %1";
234 $queryParams = [1 => [$params['fieldId'], 'Integer']];
235 $dao = CRM_Core_DAO::executeQuery($query, $queryParams);
236 if ($dao->fetch()) {
237 if ($dao->dataType == 'Money') {
238 $params['value'] = CRM_Utils_Rule::cleanMoney($params['value']);
239 }
240 switch ($dao->htmlType) {
241 case 'Autocomplete-Select':
242 case 'Select':
243 case 'Radio':
244 $query = "
245 UPDATE {$dao->tableName}
246 SET {$dao->columnName} = %1
247 WHERE id = %2";
248 if ($dao->dataType == 'Auto-complete') {
249 $dataType = "String";
250 }
251 else {
252 $dataType = $dao->dataType;
253 }
254 $queryParams = [
255 1 => [
256 $params['value'],
257 $dataType,
258 ],
259 2 => [
260 $params['optionId'],
261 'Integer',
262 ],
263 ];
264 break;
265
266 case 'Multi-Select':
267 case 'CheckBox':
268 $oldString = CRM_Core_DAO::VALUE_SEPARATOR . $oldValue . CRM_Core_DAO::VALUE_SEPARATOR;
269 $newString = CRM_Core_DAO::VALUE_SEPARATOR . $params['value'] . CRM_Core_DAO::VALUE_SEPARATOR;
270 $query = "
271 UPDATE {$dao->tableName}
272 SET {$dao->columnName} = REPLACE( {$dao->columnName}, %1, %2 )";
273 $queryParams = [
274 1 => [$oldString, 'String'],
275 2 => [$newString, 'String'],
276 ];
277 break;
278
279 default:
280 throw new CRM_Core_Exception('Invalid HTML Type');
281 }
282 $dao = CRM_Core_DAO::executeQuery($query, $queryParams);
283 }
284 }
285
286 /**
287 * When changing the value of an option this is called to update all corresponding custom data
288 *
289 * @param int $optionId
290 * @param string $newValue
291 */
292 public static function updateValue($optionId, $newValue) {
293 $optionValue = new CRM_Core_DAO_OptionValue();
294 $optionValue->id = $optionId;
295 $optionValue->find(TRUE);
296 $oldValue = $optionValue->value;
297 if ($oldValue == $newValue) {
298 return;
299 }
300
301 $customField = new CRM_Core_DAO_CustomField();
302 $customField->option_group_id = $optionValue->option_group_id;
303 $customField->find();
304 while ($customField->fetch()) {
305 $customGroup = new CRM_Core_DAO_CustomGroup();
306 $customGroup->id = $customField->custom_group_id;
307 $customGroup->find(TRUE);
308 if (CRM_Core_BAO_CustomField::isSerialized($customField)) {
309 $params = [
310 1 => [CRM_Utils_Array::implodePadded($oldValue), 'String'],
311 2 => [CRM_Utils_Array::implodePadded($newValue), 'String'],
312 3 => ['%' . CRM_Utils_Array::implodePadded($oldValue) . '%', 'String'],
313 ];
314 }
315 else {
316 $params = [
317 1 => [$oldValue, 'String'],
318 2 => [$newValue, 'String'],
319 3 => [$oldValue, 'String'],
320 ];
321 }
322 $sql = "UPDATE `{$customGroup->table_name}` SET `{$customField->column_name}` = REPLACE(`{$customField->column_name}`, %1, %2) WHERE `{$customField->column_name}` LIKE %3";
323 CRM_Core_DAO::executeQuery($sql, $params);
324 }
325 }
326
327 }