CRM-16310 - implement pagination on custom field option list page
[civicrm-core.git] / CRM / Core / BAO / CustomOption.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.6 |
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 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2015
32 * $Id$
33 *
34 */
35
36 /**
37 * Business objects for managing custom data options.
38 *
39 */
40 class CRM_Core_BAO_CustomOption {
41
42 /**
43 * Fetch object based on array of properties.
44 *
45 * @param array $params
46 * (reference ) an assoc array of name/value pairs.
47 * @param array $defaults
48 * (reference ) an assoc array to hold the flattened values.
49 *
50 * @return CRM_Core_BAO_CustomOption
51 */
52 public static function retrieve(&$params, &$defaults) {
53 $customOption = new CRM_Core_DAO_OptionValue();
54 $customOption->copyValues($params);
55 if ($customOption->find(TRUE)) {
56 CRM_Core_DAO::storeValues($customOption, $defaults);
57 return $customOption;
58 }
59 return NULL;
60 }
61
62 /**
63 * Returns all active options ordered by weight for a given field.
64 *
65 * @param int $fieldID
66 * Field whose options are needed.
67 * @param bool $inactiveNeeded Do we need inactive options ?.
68 * Do we need inactive options ?.
69 *
70 * @return array
71 * all active options for fieldId
72 */
73 public static function getCustomOption(
74 $fieldID,
75 $inactiveNeeded = FALSE
76 ) {
77 $options = array();
78 if (!$fieldID) {
79 return $options;
80 }
81
82 $field = CRM_Core_BAO_CustomField::getFieldObject($fieldID);
83
84 // get the option group id
85 $optionGroupID = $field->option_group_id;
86 if (!$optionGroupID) {
87 return $options;
88 }
89
90 $optionValues = CRM_Core_BAO_OptionValue::getOptionValuesArray($optionGroupID);
91
92 foreach ($optionValues as $id => $value) {
93 if (!$inactiveNeeded && empty($value['is_active'])) {
94 continue;
95 }
96
97 $options[$id] = array();
98 $options[$id]['id'] = $id;
99 $options[$id]['label'] = $value['label'];
100 $options[$id]['value'] = $value['value'];
101 }
102
103 CRM_Utils_Hook::customFieldOptions($fieldID, $options, TRUE);
104
105 return $options;
106 }
107
108 /**
109 * wrapper for ajax option selector.
110 *
111 * @param array $params
112 * Associated array for params record id.
113 *
114 * @return array
115 * associated array of option list
116 * -rp = rowcount
117 * -page= offset
118 */
119 static public function getOptionListSelector(&$params) {
120
121 $options = array();
122
123 //get the default value from custom fields
124 $customFieldBAO = new CRM_Core_BAO_CustomField();
125 $customFieldBAO->id = $params['fid'];
126 if ($customFieldBAO->find(TRUE)) {
127 $defaultValue = $customFieldBAO->default_value;
128 $fieldHtmlType = $customFieldBAO->html_type;
129 }
130 else {
131 CRM_Core_Error::fatal();
132 }
133 $defVal = explode(CRM_Core_DAO::VALUE_SEPARATOR,
134 substr($defaultValue, 1, -1)
135 );
136
137 // format the params
138 $params['offset'] = ($params['page'] - 1) * $params['rp'];
139 $params['rowCount'] = $params['rp'];
140 $params['sort'] = CRM_Utils_Array::value('sortBy', $params);
141
142 $field = CRM_Core_BAO_CustomField::getFieldObject($params['fid']);
143
144 // get the option group id
145 $optionGroupID = $field->option_group_id;
146 if (!$optionGroupID) {
147 return $options;
148 }
149 $queryParams = array(1 => array($optionGroupID, 'Integer'));
150 $total = "SELECT COUNT(*) FROM civicrm_option_value WHERE option_group_id = %1";
151 $params['total'] = CRM_Core_DAO::singleValueQuery($total, $queryParams);
152
153 $limit = " LIMIT {$params['offset']}, {$params['rowCount']} ";
154
155 $orderBy = ' ORDER BY options.weight asc';
156 if (!empty($params['sort'])) {
157 $orderBy = ' ORDER BY ' . CRM_Utils_Type::escape($params['sort'], 'String');
158 }
159
160 $query = "SELECT * FROM civicrm_option_value as options WHERE option_group_id = %1 {$orderBy} {$limit}";
161 $dao = CRM_Core_DAO::executeQuery($query, $queryParams);
162 $links = CRM_Custom_Page_Option::actionLinks();
163
164 $fields = array('id', 'label', 'value', 'weight');
165 $config = CRM_Core_Config::singleton();
166 while ($dao->fetch()) {
167 $options[$dao->id] = array();
168 foreach ($fields as $k) {
169 $options[$dao->id][$k] = $dao->$k;
170 }
171 $action = array_sum(array_keys($links));
172 $class = 'crm-entity';
173 // update enable/disable links depending on custom_field properties.
174 if ($dao->is_active) {
175 $action -= CRM_Core_Action::ENABLE;
176 }
177 else {
178 $class .= ' disabled';
179 $action -= CRM_Core_Action::DISABLE;
180 }
181 if ($fieldHtmlType == 'CheckBox' ||
182 $fieldHtmlType == 'AdvMulti-Select' ||
183 $fieldHtmlType == 'Multi-Select'
184 ) {
185 if (in_array($dao->value, $defVal)) {
186 $options[$dao->id]['is_default'] = '<img src="' . $config->resourceBase . 'i/check.gif" />';
187 }
188 else {
189 $options[$dao->id]['is_default'] = '';
190 }
191 }
192 else {
193 if ($defaultValue == $dao->value) {
194 $options[$dao->id]['is_default'] = '<img src="' . $config->resourceBase . 'i/check.gif" />';
195 }
196 else {
197 $options[$dao->id]['is_default'] = '';
198 }
199 }
200
201 $options[$dao->id]['class'] = $dao->id . ',' . $class;
202 $options[$dao->id]['is_active'] = !empty($dao->is_active) ? 'Yes' : 'No';
203 $options[$dao->id]['links'] = CRM_Core_Action::formLink($links,
204 $action,
205 array(
206 'id' => $dao->id,
207 'fid' => $params['fid'],
208 'gid' => $params['gid'],
209 ),
210 ts('more'),
211 FALSE,
212 'customOption.row.actions',
213 'customOption',
214 $dao->id
215 );
216 }
217 // Add order changing widget to selector
218 $returnURL = CRM_Utils_System::url('civicrm/admin/custom/group/field/option',
219 "reset=1&action=browse&gid={$params['gid']}&fid={$params['fid']}"
220 );
221 $filter = "option_group_id = {$optionGroupID}";
222 CRM_Utils_Weight::addOrder($options, 'CRM_Core_DAO_OptionValue',
223 'id', $returnURL, $filter
224 );
225
226 return $options;
227 }
228
229 /**
230 * Returns the option label for a custom field with a specific value. Handles all
231 * custom field data and html types
232 *
233 * @param int $fieldId
234 * the custom field ID.
235 * @pram $value string the value (typically from the DB) of this custom field
236 * @param $value
237 * @param string $htmlType
238 * the html type of the field (optional).
239 * @param string $dataType
240 * the data type of the field (optional).
241 *
242 * @return string
243 * the label to display for this custom field
244 */
245 public static function getOptionLabel($fieldId, $value, $htmlType = NULL, $dataType = NULL) {
246 if (!$fieldId) {
247 return NULL;
248 }
249
250 if (!$htmlType || !$dataType) {
251 $sql = "
252 SELECT html_type, data_type
253 FROM civicrm_custom_field
254 WHERE id = %1
255 ";
256 $params = array(1 => array($fieldId, 'Integer'));
257 $dao = CRM_Core_DAO::executeQuery($sql, $params);
258 if ($dao->fetch()) {
259 $htmlType = $dao->html_type;
260 $dataType = $dao->data_type;
261 }
262 else {
263 CRM_Core_Error::fatal();
264 }
265 }
266
267 $options = NULL;
268 switch ($htmlType) {
269 case 'CheckBox':
270 case 'Multi-Select':
271 case 'AdvMulti-Select':
272 case 'Select':
273 case 'Radio':
274 case 'Autocomplete-Select':
275 if (!in_array($dataType, array(
276 'Boolean',
277 'ContactReference',
278 ))
279 ) {
280 $options = self::valuesByID($fieldId);
281 }
282 }
283
284 return CRM_Core_BAO_CustomField::getDisplayValueCommon($value,
285 $options,
286 $htmlType,
287 $dataType
288 );
289 }
290
291 /**
292 * Delete Option.
293 *
294 * @param $optionId integer
295 * option id
296 *
297 */
298 public static function del($optionId) {
299 // get the customFieldID
300 $query = "
301 SELECT f.id as id, f.data_type as dataType
302 FROM civicrm_option_value v,
303 civicrm_option_group g,
304 civicrm_custom_field f
305 WHERE v.id = %1
306 AND g.id = f.option_group_id
307 AND g.id = v.option_group_id";
308 $params = array(1 => array($optionId, 'Integer'));
309 $dao = CRM_Core_DAO::executeQuery($query, $params);
310 if ($dao->fetch()) {
311 if (in_array($dao->dataType,
312 array('Int', 'Float', 'Money', 'Boolean')
313 )) {
314 $value = 0;
315 }
316 else {
317 $value = '';
318 }
319 $params = array(
320 'optionId' => $optionId,
321 'fieldId' => $dao->id,
322 'value' => $value,
323 );
324 // delete this value from the tables
325 self::updateCustomValues($params);
326
327 // also delete this option value
328 $query = "
329 DELETE
330 FROM civicrm_option_value
331 WHERE id = %1";
332 $params = array(1 => array($optionId, 'Integer'));
333 CRM_Core_DAO::executeQuery($query, $params);
334 }
335 }
336
337 /**
338 * @param array $params
339 *
340 * @throws Exception
341 */
342 public static function updateCustomValues($params) {
343 $optionDAO = new CRM_Core_DAO_OptionValue();
344 $optionDAO->id = $params['optionId'];
345 $optionDAO->find(TRUE);
346 $oldValue = $optionDAO->value;
347
348 // get the table, column, html_type and data type for this field
349 $query = "
350 SELECT g.table_name as tableName ,
351 f.column_name as columnName,
352 f.data_type as dataType,
353 f.html_type as htmlType
354 FROM civicrm_custom_group g,
355 civicrm_custom_field f
356 WHERE f.custom_group_id = g.id
357 AND f.id = %1";
358 $queryParams = array(1 => array($params['fieldId'], 'Integer'));
359 $dao = CRM_Core_DAO::executeQuery($query, $queryParams);
360 if ($dao->fetch()) {
361 if ($dao->dataType == 'Money') {
362 $params['value'] = CRM_Utils_Rule::cleanMoney($params['value']);
363 }
364 switch ($dao->htmlType) {
365 case 'Autocomplete-Select':
366 case 'Select':
367 case 'Radio':
368 $query = "
369 UPDATE {$dao->tableName}
370 SET {$dao->columnName} = %1
371 WHERE id = %2";
372 if ($dao->dataType == 'Auto-complete') {
373 $dataType = "String";
374 }
375 else {
376 $dataType = $dao->dataType;
377 }
378 $queryParams = array(
379 1 => array(
380 $params['value'],
381 $dataType,
382 ),
383 2 => array(
384 $params['optionId'],
385 'Integer',
386 ),
387 );
388 break;
389
390 case 'AdvMulti-Select':
391 case 'Multi-Select':
392 case 'CheckBox':
393 $oldString = CRM_Core_DAO::VALUE_SEPARATOR . $oldValue . CRM_Core_DAO::VALUE_SEPARATOR;
394 $newString = CRM_Core_DAO::VALUE_SEPARATOR . $params['value'] . CRM_Core_DAO::VALUE_SEPARATOR;
395 $query = "
396 UPDATE {$dao->tableName}
397 SET {$dao->columnName} = REPLACE( {$dao->columnName}, %1, %2 )";
398 $queryParams = array(
399 1 => array($oldString, 'String'),
400 2 => array($newString, 'String'),
401 );
402 break;
403
404 default:
405 CRM_Core_Error::fatal();
406 }
407 $dao = CRM_Core_DAO::executeQuery($query, $queryParams);
408 }
409 }
410
411 /**
412 * @param int $customFieldID
413 * @param int $optionGroupID
414 *
415 * @return array
416 */
417 public static function valuesByID($customFieldID, $optionGroupID = NULL) {
418 if (!$optionGroupID) {
419 $optionGroupID = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomField',
420 $customFieldID,
421 'option_group_id'
422 );
423 }
424
425 $options = $optionGroupID ? CRM_Core_OptionGroup::valuesByID($optionGroupID) : array();
426
427 CRM_Utils_Hook::customFieldOptions($customFieldID, $options, FALSE);
428
429 return $options;
430 }
431
432 }