fixes to value and weight handling CRM-12133
[civicrm-core.git] / CRM / Core / BAO / OptionValue.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.3 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
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-2013
32 * $Id$
33 *
34 */
35class CRM_Core_BAO_OptionValue extends CRM_Core_DAO_OptionValue {
36
37 /**
38 * class constructor
39 */
40 function __construct() {
41 parent::__construct();
42 }
9fe6051a 43 /**
e99c9805 44 * Create option value - note that the create function calls 'add' but
c87bbced 45 * has more business logic
c87bbced 46 *
47 * @param array $params input parameters
48 */
49 static function create($params) {
50 if (empty($params['id'])){
51 self::setDefaults($params);
52 }
53 $ids = array();
54 if (CRM_Utils_Array::value('id', $params)) {
55 $ids = array('optionValue' => $params['id']);
56 }
57 return CRM_Core_BAO_OptionValue::add($params, $ids);
58 ;
59 }
60 /**
61 * Set default Parameters
62 * This functions sets default parameters if not set:
63 * - name & label are set to each other as required (it might make more sense for one
64 * to be required but this would mean a change to the api level)
9fe6051a 65 * - weight & value will be set to their respective option groups next values
66 * if nothing is passed in.
67 *
68 * Note this function does not check for presence of $params['id'] so should only be called
69 * if 'id' is not present
c87bbced 70 *
9fe6051a 71 * @param array $params
c87bbced 72 */
73 static function setDefaults(&$params){
74 if(empty($params['label'])){
75 $params['label'] = $params['name'];
76 }
77 if(empty($params['name'])){
78 $params['name'] = $params['label'];
79 }
80 if(empty($params['weight'])){
9fe6051a 81 $params['weight'] = (int) CRM_Utils_Weight::getDefaultWeight('CRM_Core_DAO_OptionValue',
82 array('option_group_id' => $params['option_group_id']));
c87bbced 83 }
84 if(empty($params['value'])){
9fe6051a 85 $params['value'] = self::getNextValue($params);
c87bbced 86 }
87 }
9fe6051a 88 /**
89 * Get next available value
90 * We will take the highest numeric value (or 0 if no numeric values exist)
91 * and add one. The calling function is responsible for any
92 * more complex decision making
93 * @param array $params
94 */
95 static function getNextValue($params){
96 $bao = new CRM_Core_BAO_OptionValue();
97 $bao->option_group_id = $params['option_group_id'];
98 if(isset($params['domain_id'])){
99 $bao->domain_id = $params['domain_id'];
100 }
101 $bao->selectAdd();
102 $bao->whereAdd("value REGEXP '^[0-9]+$'");
103 $bao->selectAdd('(ROUND(COALESCE(MAX(value),0)) +1) as nextvalue');
104 $bao->find(TRUE);
105 return $bao->nextvalue;
106 }
6a488035
TO
107 /**
108 * Takes a bunch of params that are needed to match certain criteria and
109 * retrieves the relevant objects. Typically the valid params are only
110 * contact_id. We'll tweak this function to be more full featured over a period
111 * of time. This is the inverse function of create. It also stores all the retrieved
112 * values in the default array
113 *
114 * @param array $params (reference ) an assoc array of name/value pairs
115 * @param array $defaults (reference ) an assoc array to hold the flattened values
116 *
117 * @return object CRM_Core_BAO_OptionValue object
118 * @access public
119 * @static
120 */
121 static function retrieve(&$params, &$defaults) {
122 $optionValue = new CRM_Core_DAO_OptionValue();
123 $optionValue->copyValues($params);
124 if ($optionValue->find(TRUE)) {
125 CRM_Core_DAO::storeValues($optionValue, $defaults);
126 return $optionValue;
127 }
128 return NULL;
129 }
130
131 /**
132 * update the is_active flag in the db
133 *
134 * @param int $id id of the database record
135 * @param boolean $is_active value we want to set the is_active field
136 *
137 * @return Object DAO object on sucess, null otherwise
138 * @static
139 */
140 static function setIsActive($id, $is_active) {
141 return CRM_Core_DAO::setFieldValue('CRM_Core_DAO_OptionValue', $id, 'is_active', $is_active);
142 }
143
144 /**
145 * Function to add an Option Value
146 *
147 * @param array $params reference array contains the values submitted by the form
148 * @param array $ids reference array contains the id
149 *
150 * @access public
151 * @static
152 *
153 * @return object
154 */
155 static function add(&$params, &$ids) {
156 // CRM-10921: do not reset attributes to default if this is an update
9fe6051a 157 //@todo consider if defaults are being set in the right place. 'dumb' defaults like
158 // these would be usefully set @ the api layer so they are visible to api users
159 // complex defaults like the domain id below would make sense in the setDefauls function
160 // but unclear what other ways this function is being used
6a488035
TO
161 if (!CRM_Utils_Array::value('optionValue', $ids)) {
162 $params['is_active'] = CRM_Utils_Array::value('is_active', $params, FALSE);
163 $params['is_default'] = CRM_Utils_Array::value('is_default', $params, FALSE);
164 $params['is_optgroup'] = CRM_Utils_Array::value('is_optgroup', $params, FALSE);
165 $params['filter'] = CRM_Utils_Array::value('filter', $params, FALSE);
166 }
167
168 // action is taken depending upon the mode
169 $optionValue = new CRM_Core_DAO_OptionValue();
170 $optionValue->copyValues($params);
171
172 if (CRM_Utils_Array::value('is_default', $params)) {
173 $query = 'UPDATE civicrm_option_value SET is_default = 0 WHERE option_group_id = %1';
174
175 // tweak default reset, and allow multiple default within group.
176 if ($resetDefaultFor = CRM_Utils_Array::value('reset_default_for', $params)) {
177 if (is_array($resetDefaultFor)) {
178 $colName = key($resetDefaultFor);
179 $colVal = $resetDefaultFor[$colName];
180 $query .= " AND ( $colName IN ( $colVal ) )";
181 }
182 }
183
184 $p = array(1 => array($params['option_group_id'], 'Integer'));
185 CRM_Core_DAO::executeQuery($query, $p);
186 }
6a488035
TO
187 $groupName = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup',
188 $params['option_group_id'], 'name', 'id'
189 );
190 if (in_array($groupName, CRM_Core_OptionGroup::$_domainIDGroups)) {
191 $optionValue->domain_id = CRM_Utils_Array::value('domain_id', $params, CRM_Core_Config::domainID());
192 }
193
194 $optionValue->id = CRM_Utils_Array::value('optionValue', $ids);
195 $optionValue->save();
196 return $optionValue;
197 }
198
199 /**
200 * Function to delete Option Value
201 *
202 * @param int $optionGroupId Id of the Option Group to be deleted.
203 *
204 * @return boolean
205 *
206 * @access public
207 * @static
208 */
209 static function del($optionValueId) {
210 $optionValue = new CRM_Core_DAO_OptionValue();
211 $optionValue->id = $optionValueId;
212 if (self::updateRecords($optionValueId, CRM_Core_Action::DELETE)) {
213 return $optionValue->delete();
214 }
215 return FALSE;
216 }
217
218 /**
219 * Function to retrieve activity type label and description
220 *
221 * @param int $activityTypeId activity type id
222 *
223 * @return array label and description
224 * @static
225 * @access public
226 */
227 static function getActivityTypeDetails($activityTypeId) {
228 $query = "SELECT civicrm_option_value.label, civicrm_option_value.description
229 FROM civicrm_option_value
230 LEFT JOIN civicrm_option_group ON ( civicrm_option_value.option_group_id = civicrm_option_group.id )
231 WHERE civicrm_option_group.name = 'activity_type'
232 AND civicrm_option_value.value = {$activityTypeId} ";
233
234 $dao = CRM_Core_DAO::executeQuery($query);
235
236 $dao->fetch();
237
238 return array($dao->label, $dao->description);
239 }
240
241 /**
242 * Get the Option Value title.
243 *
244 * @param int $id id of Option Value
245 *
246 * @return string title
247 *
248 * @access public
249 * @static
250 *
251 */
252 public static function getTitle($id) {
253 return CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionValue', $id, 'label');
254 }
255
256 /**
257 * updates contacts affected by the option value passed.
258 *
259 * @param Integer $optionValueId the option value id.
260 * @param int $action the action describing whether prefix/suffix was UPDATED or DELETED
261 *
262 * @return void
263 */
264 static function updateRecords(&$optionValueId, $action) {
265 //finding group name
266 $optionValue = new CRM_Core_DAO_OptionValue();
267 $optionValue->id = $optionValueId;
268 $optionValue->find(TRUE);
269
270 $optionGroup = new CRM_Core_DAO_OptionGroup();
271 $optionGroup->id = $optionValue->option_group_id;
272 $optionGroup->find(TRUE);
273
274 // group name
275 $gName = $optionGroup->name;
276 // value
277 $value = $optionValue->value;
278
279 // get the proper group name & affected field name
280 $individuals = array(
281 'gender' => 'gender_id',
282 'individual_prefix' => 'prefix_id',
283 'individual_suffix' => 'suffix_id',
284 );
285 $contributions = array('payment_instrument' => 'payment_instrument_id');
286 $activities = array('activity_type' => 'activity_type_id');
287 $participant = array('participant_role' => 'role_id');
288 $eventType = array('event_type' => 'event_type_id');
289 $aclRole = array('acl_role' => 'acl_role_id');
290
291 $all = array_merge($individuals, $contributions, $activities, $participant, $eventType, $aclRole);
292 $fieldName = '';
293
294 foreach ($all as $name => $id) {
295 if ($gName == $name) {
296 $fieldName = $id;
297 }
298 }
299 if ($fieldName == '') {
300 return TRUE;
301 }
302
303 if (array_key_exists($gName, $individuals)) {
304 $contactDAO = new CRM_Contact_DAO_Contact();
305
306 $contactDAO->$fieldName = $value;
307 $contactDAO->find();
308
309 while ($contactDAO->fetch()) {
310 if ($action == CRM_Core_Action::DELETE) {
311 $contact = new CRM_Contact_DAO_Contact();
312 $contact->id = $contactDAO->id;
313 $contact->find(TRUE);
314
315 // make sure dates doesn't get reset
316 $contact->birth_date = CRM_Utils_Date::isoToMysql($contact->birth_date);
317 $contact->deceased_date = CRM_Utils_Date::isoToMysql($contact->deceased_date);
318 $contact->$fieldName = 'NULL';
319 $contact->save();
320 }
321 }
322
323 return TRUE;
324 }
325
326 if (array_key_exists($gName, $contributions)) {
327 $contribution = new CRM_Contribute_DAO_Contribution();
328 $contribution->$fieldName = $value;
329 $contribution->find();
330 while ($contribution->fetch()) {
331 if ($action == CRM_Core_Action::DELETE) {
332 $contribution->$fieldName = 'NULL';
333 $contribution->save();
334 }
335 }
336 return TRUE;
337 }
338
339 if (array_key_exists($gName, $activities)) {
340 $activity = new CRM_Activity_DAO_Activity();
341 $activity->$fieldName = $value;
342 $activity->find();
343 while ($activity->fetch()) {
344 $activity->delete();
345 }
346 return TRUE;
347 }
348
349 //delete participant role, type and event type option value
350 if (array_key_exists($gName, $participant)) {
351 $participantValue = new CRM_Event_DAO_Participant();
352 $participantValue->$fieldName = $value;
353 if ($participantValue->find(TRUE)) {
354 return FALSE;
355 }
356 return TRUE;
357 }
358
359 //delete event type option value
360 if (array_key_exists($gName, $eventType)) {
361 $event = new CRM_Event_DAO_Event();
362 $event->$fieldName = $value;
363 if ($event->find(TRUE)) {
364 return FALSE;
365 }
366 return TRUE;
367 }
368
369 //delete acl_role option value
370 if (array_key_exists($gName, $aclRole)) {
371 $entityRole = new CRM_ACL_DAO_EntityRole();
372 $entityRole->$fieldName = $value;
373
374 $aclDAO = new CRM_ACL_DAO_ACL();
375 $aclDAO->entity_id = $value;
376 if ($entityRole->find(TRUE) || $aclDAO->find(TRUE)) {
377 return FALSE;
378 }
379 return TRUE;
380 }
381 }
382
383 /**
384 * updates options values weights.
385 *
386 * @param int $opGroupIde option group id.
387 * @param array $opWeights options value , weight pair
388 *
389 * @return void
390 * @access public
391 * @static
392 */
393 static function updateOptionWeights($opGroupId, $opWeights) {
394 if (!is_array($opWeights) || empty($opWeights)) {
395 return;
396 }
397
398 foreach ($opWeights as $opValue => $opWeight) {
399 $optionValue = new CRM_Core_DAO_OptionValue();
400 $optionValue->option_group_id = $opGroupId;
401 $optionValue->value = $opValue;
402 if ($optionValue->find(TRUE)) {
403 $optionValue->weight = $opWeight;
404 $optionValue->save();
405 }
406 $optionValue->free();
407 }
408 }
409
410 /**
411 * Get the values of all option values given an option group ID. Store in system cache
412 * Does not take any filtering arguments. The object is to avoid hitting the DB and retrieve
413 * from memory
414 *
415 * @param int $optionGroupID the option group for which we want the values from
416 *
417 * @return array an array of array of values for this option group
418 * @static
419 * @public
420 */
421 static function getOptionValuesArray($optionGroupID) {
422 // check if we can get the field values from the system cache
423 $cacheKey = "CRM_Core_BAO_OptionValue_OptionGroupID_{$optionGroupID}";
424 $cache = CRM_Utils_Cache::singleton();
425 $optionValues = $cache->get($cacheKey);
426 if (empty($optionValues)) {
427 $dao = new CRM_Core_DAO_OptionValue();
428 $dao->option_group_id = $optionGroupID;
429 $dao->orderBy('weight ASC, label ASC');
430 $dao->find();
431
432 $optionValues = array();
433 while ($dao->fetch()) {
434 $optionValues[$dao->id] = array();
435 CRM_Core_DAO::storeValues($dao, $optionValues[$dao->id]);
436 }
437
438 $cache->set($cacheKey, $optionValues);
439 }
440
441 return $optionValues;
442 }
443
444 /**
445 * Get the values of all option values given an option group ID as a key => value pair
446 * Use above cached function to make it super efficient
447 *
448 * @param int $optionGroupID the option group for which we want the values from
449 *
450 * @return array an associative array of label, value pairs
451 * @static
452 * @public
453 */
454 static function getOptionValuesAssocArray($optionGroupID) {
455 $optionValues = self::getOptionValuesArray($optionGroupID);
456
457 $options = array();
458 foreach ($optionValues as $id => $value) {
459 $options[$value['value']] = $value['label'];
460 }
461 return $options;
462 }
463 /**
464 * Get the values of all option values given an option group Name as a key => value pair
465 * Use above cached function to make it super efficient
466 *
467 * @param string $optionGroupName the option group name for which we want the values from
468 *
469 * @return array an associative array of label, value pairs
470 * @static
471 * @public
472 */
473 static function getOptionValuesAssocArrayFromName($optionGroupName) {
474 $dao = new CRM_Core_DAO_OptionGroup();
475 $dao->name = $optionGroupName;
476 $dao->selectAdd();
477 $dao->selectAdd('id');
478 $dao->find(TRUE);
479 $optionValues = self::getOptionValuesArray($dao->id);
480
481 $options = array();
482 foreach ($optionValues as $id => $value) {
483 $options[$value['value']] = $value['label'];
484 }
485 return $options;
486 }
487
488}
489