HR-322 - Ensure customFieldOptions hook is always called for custom fields
[civicrm-core.git] / CRM / Core / PseudoConstant.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
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 * Stores all constants and pseudo constants for CRM application.
31 *
32 * examples of constants are "Contact Type" which will always be either
33 * 'Individual', 'Household', 'Organization'.
34 *
35 * pseudo constants are entities from the database whose values rarely
36 * change. examples are list of countries, states, location types,
37 * relationship types.
38 *
39 * currently we're getting the data from the underlying database. this
40 * will be reworked to use caching.
41 *
42 * Note: All pseudoconstants should be uninitialized or default to NULL.
43 * This provides greater consistency/predictability after flushing.
44 *
45 * @package CRM
46 * @copyright CiviCRM LLC (c) 2004-2014
47 * $Id$
48 *
49 */
50 class CRM_Core_PseudoConstant {
51
52 /**
53 * static cache for pseudoconstant arrays
54 * @var array
55 * @static
56 */
57 private static $cache;
58
59 /**
60 * DEPRECATED. Please use the buildOptions() method in the appropriate BAO object.
61 *
62 * activity type
63 * @var array
64 * @static
65 */
66 private static $activityType;
67
68 /**
69 * states, provinces
70 * @var array
71 * @static
72 */
73 private static $stateProvince;
74
75 /**
76 * counties
77 * @var array
78 * @static
79 */
80 private static $county;
81
82 /**
83 * states/provinces abbreviations
84 * @var array
85 * @static
86 */
87 private static $stateProvinceAbbreviation;
88
89 /**
90 * country
91 * @var array
92 * @static
93 */
94 private static $country;
95
96 /**
97 * countryIsoCode
98 * @var array
99 * @static
100 */
101 private static $countryIsoCode;
102
103 /**
104 * DEPRECATED. Please use the buildOptions() method in the appropriate BAO object.
105 *
106 * group
107 * @var array
108 * @static
109 */
110 private static $group;
111
112 /**
113 * groupIterator
114 * @var mixed
115 * @static
116 */
117 private static $groupIterator;
118
119 /**
120 * relationshipType
121 * @var array
122 * @static
123 */
124 private static $relationshipType;
125
126 /**
127 * civicrm groups that are not smart groups
128 * @var array
129 * @static
130 */
131 private static $staticGroup;
132
133 /**
134 * currency codes
135 * @var array
136 * @static
137 */
138 private static $currencyCode;
139
140 /**
141 * payment processor
142 * @var array
143 * @static
144 */
145 private static $paymentProcessor;
146
147 /**
148 * payment processor types
149 * @var array
150 * @static
151 */
152 private static $paymentProcessorType;
153
154 /**
155 * World Region
156 * @var array
157 * @static
158 */
159 private static $worldRegions;
160
161 /**
162 * DEPRECATED. Please use the buildOptions() method in the appropriate BAO object.
163 *
164 * activity status
165 * @var array
166 * @static
167 */
168 private static $activityStatus;
169
170 /**
171 * Visibility
172 * @var array
173 * @static
174 */
175 private static $visibility;
176
177 /**
178 * Greetings
179 * @var array
180 * @static
181 */
182 private static $greeting;
183
184 /**
185 * Default Greetings
186 * @var array
187 * @static
188 */
189 private static $greetingDefaults;
190
191 /**
192 * Extensions of type module
193 * @var array
194 * @static
195 */
196 private static $extensions;
197
198 /**
199 * Financial Account Type
200 * @var array
201 * @static
202 */
203 private static $accountOptionValues;
204
205 /**
206 * Low-level option getter, rarely accessed directly.
207 * NOTE: Rather than calling this function directly use CRM_*_BAO_*::buildOptions()
208 * @see http://wiki.civicrm.org/confluence/display/CRMDOC/Pseudoconstant+%28option+list%29+Reference
209 *
210 * @param String $daoName
211 * @param String $fieldName
212 * @param Array $params
213 * - name string name of the option group
214 * - flip boolean results are return in id => label format if false
215 * if true, the results are reversed
216 * - grouping boolean if true, return the value in 'grouping' column (currently unsupported for tables other than option_value)
217 * - localize boolean if true, localize the results before returning
218 * - condition string|array add condition(s) to the sql query - will be concatenated using 'AND'
219 * - keyColumn string the column to use for 'id'
220 * - labelColumn string the column to use for 'label'
221 * - orderColumn string the column to use for sorting, defaults to 'weight' column if one exists, else defaults to labelColumn
222 * - onlyActive boolean return only the action option values
223 * - fresh boolean ignore cache entries and go back to DB
224 * @param String $context: Context string
225 *
226 * @return Array|bool - array on success, FALSE on error.
227 *
228 * @static
229 */
230 public static function get($daoName, $fieldName, $params = array(), $context = NULL) {
231 CRM_Core_DAO::buildOptionsContext($context);
232 $flip = !empty($params['flip']);
233 // Merge params with defaults
234 $params += array(
235 'grouping' => FALSE,
236 'localize' => FALSE,
237 'onlyActive' => ($context == 'validate' || $context == 'get') ? FALSE : TRUE,
238 'fresh' => FALSE,
239 );
240
241 // Custom fields are not in the schema
242 if (strpos($fieldName, 'custom_') === 0 && is_numeric($fieldName[7])) {
243 $customField = new CRM_Core_DAO_CustomField();
244 $customField->id = (int) substr($fieldName, 7);
245 $customField->find(TRUE);
246 $options = FALSE;
247
248 if (!empty($customField->option_group_id)) {
249 $options = CRM_Core_OptionGroup::valuesByID($customField->option_group_id,
250 FALSE,
251 $params['grouping'],
252 $params['localize'],
253 // Note: for custom fields the 'name' column is NULL
254 CRM_Utils_Array::value('labelColumn', $params, 'label'),
255 $params['onlyActive'],
256 $params['fresh']
257 );
258 }
259 else {
260 if ($customField->data_type === 'StateProvince') {
261 $options = self::stateProvince();
262 }
263 elseif ($customField->data_type === 'Country') {
264 $options = $context == 'validate' ? self::countryIsoCode() : self::country();
265 }
266 elseif ($customField->data_type === 'Boolean') {
267 $options = $context == 'validate' ? array(0, 1) : array(1 => ts('Yes'), 0 => ts('No'));
268 }
269 }
270 CRM_Utils_Hook::customFieldOptions($customField->id, $options, FALSE);
271 if ($options && $flip) {
272 $options = array_flip($options);
273 }
274 $customField->free();
275 return $options;
276 }
277
278 // Core field: load schema
279 $dao = new $daoName;
280 $fieldSpec = $dao->getFieldSpec($fieldName);
281 $dao->free();
282 // If neither worked then this field doesn't exist. Return false.
283 if (empty($fieldSpec)) {
284 return FALSE;
285 }
286
287 elseif (!empty($fieldSpec['pseudoconstant'])) {
288 $pseudoconstant = $fieldSpec['pseudoconstant'];
289
290 // if callback is specified..
291 if(!empty($pseudoconstant['callback'])) {
292 list($className, $fnName) = explode('::', $pseudoconstant['callback']);
293 if (method_exists($className, $fnName)) {
294 return call_user_func(array($className, $fnName));
295 }
296 }
297
298 // Merge params with schema defaults
299 $params += array(
300 'condition' => CRM_Utils_Array::value('condition', $pseudoconstant, array()),
301 'keyColumn' => CRM_Utils_Array::value('keyColumn', $pseudoconstant),
302 'labelColumn' => CRM_Utils_Array::value('labelColumn', $pseudoconstant),
303 );
304
305 // Fetch option group from option_value table
306 if(!empty($pseudoconstant['optionGroupName'])) {
307 if ($context == 'validate') {
308 $params['labelColumn'] = 'name';
309 }
310 // Call our generic fn for retrieving from the option_value table
311 return CRM_Core_OptionGroup::values(
312 $pseudoconstant['optionGroupName'],
313 $flip,
314 $params['grouping'],
315 $params['localize'],
316 $params['condition'] ? ' AND ' . implode(' AND ', (array) $params['condition']) : NULL,
317 $params['labelColumn'] ? $params['labelColumn'] : 'label',
318 $params['onlyActive'],
319 $params['fresh'],
320 $params['keyColumn'] ? $params['keyColumn'] : 'value'
321 );
322 }
323
324 // Fetch options from other tables
325 if (!empty($pseudoconstant['table'])) {
326 // Normalize params so the serialized cache string will be consistent.
327 CRM_Utils_Array::remove($params, 'flip', 'fresh');
328 ksort($params);
329 $cacheKey = $daoName . $fieldName . serialize($params);
330
331 // Retrieve cached options
332 if (isset(self::$cache[$cacheKey]) && empty($params['fresh'])) {
333 $output = self::$cache[$cacheKey];
334 }
335 else {
336 $daoName = CRM_Core_DAO_AllCoreTables::getClassForTable($pseudoconstant['table']);
337 if (!class_exists($daoName)) {
338 return FALSE;
339 }
340 // Get list of fields for the option table
341 $dao = new $daoName;
342 $availableFields = array_keys($dao->fieldKeys());
343 $dao->free();
344
345 $select = "SELECT %1 AS id, %2 AS label";
346 $from = "FROM %3";
347 $wheres = array();
348 $order = "ORDER BY %2";
349
350 // Use machine name instead of label in validate context
351 if ($context == 'validate') {
352 if (!empty($pseudoconstant['nameColumn'])) {
353 $params['labelColumn'] = $pseudoconstant['nameColumn'];
354 }
355 elseif (in_array('name', $availableFields)) {
356 $params['labelColumn'] = 'name';
357 }
358 }
359 // Condition param can be passed as an sql clause string or an array of clauses
360 if (!empty($params['condition'])) {
361 $wheres[] = implode(' AND ', (array) $params['condition']);
362 }
363 // onlyActive param will automatically filter on common flags
364 if (!empty($params['onlyActive'])) {
365 foreach (array('is_active' => 1, 'is_deleted' => 0, 'is_test' => 0) as $flag => $val) {
366 if (in_array($flag, $availableFields)) {
367 $wheres[] = "$flag = $val";
368 }
369 }
370 }
371 // Filter domain specific options
372 if (in_array('domain_id', $availableFields)) {
373 $wheres[] = 'domain_id = ' . CRM_Core_Config::domainID();
374 }
375 $queryParams = array(
376 1 => array($params['keyColumn'], 'String', CRM_Core_DAO::QUERY_FORMAT_NO_QUOTES),
377 2 => array($params['labelColumn'], 'String', CRM_Core_DAO::QUERY_FORMAT_NO_QUOTES),
378 3 => array($pseudoconstant['table'], 'String', CRM_Core_DAO::QUERY_FORMAT_NO_QUOTES),
379 );
380 // Add orderColumn param
381 if (!empty($params['orderColumn'])) {
382 $queryParams[4] = array($params['orderColumn'], 'String', CRM_Core_DAO::QUERY_FORMAT_NO_QUOTES);
383 $order = "ORDER BY %4";
384 }
385 // Support no sorting if $params[orderColumn] is FALSE
386 elseif (isset($params['orderColumn']) && $params['orderColumn'] === FALSE) {
387 $order = '';
388 }
389 // Default to 'weight' if that column exists
390 elseif (in_array('weight', $availableFields)) {
391 $order = "ORDER BY weight";
392 }
393
394 $output = array();
395 $query = "$select $from";
396 if ($wheres) {
397 $query .= " WHERE " . implode($wheres, ' AND ');
398 }
399 $query .= ' ' . $order;
400 $dao = CRM_Core_DAO::executeQuery($query, $queryParams);
401 while ($dao->fetch()) {
402 $output[$dao->id] = $dao->label;
403 }
404 $dao->free();
405 // Localize results
406 if (!empty($params['localize']) || $pseudoconstant['table'] == 'civicrm_country' || $pseudoconstant['table'] == 'civicrm_state_province') {
407 $I18nParams = array();
408 if ($pseudoconstant['table'] == 'civicrm_country') {
409 $I18nParams['context'] = 'country';
410 }
411 if ($pseudoconstant['table'] == 'civicrm_state_province') {
412 $I18nParams['context'] = 'province';
413 }
414 $i18n = CRM_Core_I18n::singleton();
415 $i18n->localizeArray($output, $I18nParams);
416 // Maintain sort by label
417 if ($order == "ORDER BY %2") {
418 CRM_Utils_Array::asort($output);
419 }
420 }
421 self::$cache[$cacheKey] = $output;
422 }
423 return $flip ? array_flip($output) : $output;
424 }
425 }
426
427 // Return "Yes" and "No" for boolean fields
428 elseif (CRM_Utils_Array::value('type', $fieldSpec) === CRM_Utils_Type::T_BOOLEAN) {
429 $output = $context == 'validate' ? array(0, 1) : array(1 => ts('Yes'), 0 => ts('No'));
430 return $flip ? array_flip($output) : $output;
431 }
432 // If we're still here, it's an error. Return FALSE.
433 return FALSE;
434 }
435
436 /**
437 * Fetch the translated label for a field given its key
438 *
439 * @param String $baoName
440 * @param String $fieldName
441 * @param String|Int $key
442 *
443 * TODO: Accept multivalued input?
444 *
445 * @return bool|null|string
446 * FALSE if the given field has no associated option list
447 * NULL if the given key has no corresponding option
448 * String if label is found
449 */
450 static function getLabel($baoName, $fieldName, $key) {
451 $values = $baoName::buildOptions($fieldName, 'get');
452 if ($values === FALSE) {
453 return FALSE;
454 }
455 return CRM_Utils_Array::value($key, $values);
456 }
457
458 /**
459 * Fetch the machine name for a field given its key
460 *
461 * @param String $baoName
462 * @param String $fieldName
463 * @param String|Int $key
464 *
465 * @return bool|null|string
466 * FALSE if the given field has no associated option list
467 * NULL if the given key has no corresponding option
468 * String if label is found
469 */
470 static function getName($baoName, $fieldName, $key) {
471 $values = $baoName::buildOptions($fieldName, 'validate');
472 if ($values === FALSE) {
473 return FALSE;
474 }
475 return CRM_Utils_Array::value($key, $values);
476 }
477
478 /**
479 * Fetch the key for a field option given its name
480 *
481 * @param String $baoName
482 * @param String $fieldName
483 * @param String|Int $value
484 *
485 * @return bool|null|string|number
486 * FALSE if the given field has no associated option list
487 * NULL if the given key has no corresponding option
488 * String|Number if key is found
489 */
490 static function getKey($baoName, $fieldName, $value) {
491 $values = $baoName::buildOptions($fieldName, 'validate');
492 if ($values === FALSE) {
493 return FALSE;
494 }
495 return CRM_Utils_Array::key($value, $values);
496 }
497
498 /**
499 * Lookup the admin page at which a field's option list can be edited
500 * @param $fieldSpec
501 * @return string|null
502 */
503 static function getOptionEditUrl($fieldSpec) {
504 // If it's an option group, that's easy
505 if (!empty($fieldSpec['pseudoconstant']['optionGroupName'])) {
506 return 'civicrm/admin/options/' . $fieldSpec['pseudoconstant']['optionGroupName'];
507 }
508 // For everything else...
509 elseif (!empty($fieldSpec['pseudoconstant']['table'])) {
510 $daoName = CRM_Core_DAO_AllCoreTables::getClassForTable($fieldSpec['pseudoconstant']['table']);
511 if (!$daoName) {
512 return NULL;
513 }
514 // We don't have good mapping so have to do a bit of guesswork from the menu
515 list(, $parent, , $child) = explode('_', $daoName);
516 $sql = "SELECT path FROM civicrm_menu
517 WHERE page_callback LIKE '%CRM_Admin_Page_$child%' OR page_callback LIKE '%CRM_{$parent}_Page_$child%'
518 ORDER BY page_callback
519 LIMIT 1";
520 return CRM_Core_Dao::singleValueQuery($sql);
521 }
522 return NULL;
523 }
524
525 /**
526 * DEPRECATED generic populate method
527 * All pseudoconstant functions that use this method are also deprecated.
528 *
529 * The static array $var is populated from the db
530 * using the <b>$name DAO</b>.
531 *
532 * Note: any database errors will be trapped by the DAO.
533 *
534 * @param array $var the associative array we will fill
535 * @param string $name the name of the DAO
536 * @param boolean $all get all objects. default is to get only active ones.
537 * @param string $retrieve the field that we are interested in (normally name, differs in some objects)
538 * @param string $filter the field that we want to filter the result set with
539 * @param string $condition the condition that gets passed to the final query as the WHERE clause
540 *
541 * @return void
542 * @access public
543 * @static
544 */
545 public static function populate(
546 &$var,
547 $name,
548 $all = FALSE,
549 $retrieve = 'name',
550 $filter = 'is_active',
551 $condition = NULL,
552 $orderby = NULL,
553 $key = 'id',
554 $force = NULL
555 ) {
556 $cacheKey = "CRM_PC_{$name}_{$all}_{$key}_{$retrieve}_{$filter}_{$condition}_{$orderby}";
557 $cache = CRM_Utils_Cache::singleton();
558 $var = $cache->get($cacheKey);
559 if ($var && empty($force)) {
560 return $var;
561 }
562
563 $object = new $name ( );
564
565 $object->selectAdd();
566 $object->selectAdd("$key, $retrieve");
567 if ($condition) {
568 $object->whereAdd($condition);
569 }
570
571 if (!$orderby) {
572 $object->orderBy($retrieve);
573 }
574 else {
575 $object->orderBy($orderby);
576 }
577
578 if (!$all) {
579 $object->$filter = 1;
580 }
581
582 $object->find();
583 $var = array();
584 while ($object->fetch()) {
585 $var[$object->$key] = $object->$retrieve;
586 }
587
588 $cache->set($cacheKey, $var);
589 }
590
591 /**
592 * Flush given pseudoconstant so it can be reread from db
593 * nex time it's requested.
594 *
595 * @access public
596 * @static
597 *
598 * @param boolean $name pseudoconstant to be flushed
599 *
600 */
601 public static function flush($name = 'cache') {
602 if (isset(self::$$name)) {
603 self::$$name = NULL;
604 }
605 if ($name == 'cache') {
606 CRM_Core_OptionGroup::flushAll();
607 }
608 }
609
610 /**
611 * DEPRECATED. Please use the buildOptions() method in the appropriate BAO object.
612 *
613 * Get all Activty types.
614 *
615 * The static array activityType is returned
616 *
617 * @param boolean $all - get All Activity types - default is to get only active ones.
618 *
619 * @access public
620 * @static
621 *
622 * @return array - array reference of all activity types.
623 */
624 public static function &activityType() {
625 $args = func_get_args();
626 $all = CRM_Utils_Array::value(0, $args, TRUE);
627 $includeCaseActivities = CRM_Utils_Array::value(1, $args, FALSE);
628 $reset = CRM_Utils_Array::value(2, $args, FALSE);
629 $returnColumn = CRM_Utils_Array::value(3, $args, 'label');
630 $includeCampaignActivities = CRM_Utils_Array::value(4, $args, FALSE);
631 $onlyComponentActivities = CRM_Utils_Array::value(5, $args, FALSE);
632 $index = (int) $all . '_' . $returnColumn . '_' . (int) $includeCaseActivities;
633 $index .= '_' . (int) $includeCampaignActivities;
634 $index .= '_' . (int) $onlyComponentActivities;
635
636 if (NULL === self::$activityType) {
637 self::$activityType = array();
638 }
639
640 if (!isset(self::$activityType[$index]) || $reset) {
641 $condition = NULL;
642 if (!$all) {
643 $condition = 'AND filter = 0';
644 }
645 $componentClause = " v.component_id IS NULL";
646 if ($onlyComponentActivities) {
647 $componentClause = " v.component_id IS NOT NULL";
648 }
649
650 $componentIds = array();
651 $compInfo = CRM_Core_Component::getEnabledComponents();
652
653 // build filter for listing activity types only if their
654 // respective components are enabled
655 foreach ($compInfo as $compName => $compObj) {
656 if ($compName == 'CiviCase') {
657 if ($includeCaseActivities) {
658 $componentIds[] = $compObj->componentID;
659 }
660 }
661 elseif ($compName == 'CiviCampaign') {
662 if ($includeCampaignActivities) {
663 $componentIds[] = $compObj->componentID;
664 }
665 }
666 else {
667 $componentIds[] = $compObj->componentID;
668 }
669 }
670
671 if (count($componentIds)) {
672 $componentIds = implode(',', $componentIds);
673 $componentClause = " ($componentClause OR v.component_id IN ($componentIds))";
674 if ($onlyComponentActivities) {
675 $componentClause = " ( v.component_id IN ($componentIds ) )";
676 }
677 }
678 $condition = $condition . ' AND ' . $componentClause;
679
680 self::$activityType[$index] = CRM_Core_OptionGroup::values('activity_type', FALSE, FALSE, FALSE, $condition, $returnColumn);
681 }
682 return self::$activityType[$index];
683 }
684
685 /**
686 * Get all the State/Province from database.
687 *
688 * The static array stateProvince is returned, and if it's
689 * called the first time, the <b>State Province DAO</b> is used
690 * to get all the States.
691 *
692 * Note: any database errors will be trapped by the DAO.
693 *
694 * @access public
695 * @static
696 *
697 * @param int $id - Optional id to return
698 *
699 * @return array - array reference of all State/Provinces.
700 *
701 */
702 public static function &stateProvince($id = FALSE, $limit = TRUE) {
703 if (($id && !CRM_Utils_Array::value($id, self::$stateProvince)) || !self::$stateProvince || !$id) {
704 $whereClause = FALSE;
705 $config = CRM_Core_Config::singleton();
706 if ($limit) {
707 $countryIsoCodes = self::countryIsoCode();
708 $limitCodes = $config->provinceLimit();
709 $limitIds = array();
710 foreach ($limitCodes as $code) {
711 $limitIds = array_merge($limitIds, array_keys($countryIsoCodes, $code));
712 }
713 if (!empty($limitIds)) {
714 $whereClause = 'country_id IN (' . implode(', ', $limitIds) . ')';
715 }
716 else {
717 $whereClause = FALSE;
718 }
719 }
720 self::populate(self::$stateProvince, 'CRM_Core_DAO_StateProvince', TRUE, 'name', 'is_active', $whereClause);
721
722 // localise the province names if in an non-en_US locale
723 global $tsLocale;
724 if ($tsLocale != '' and $tsLocale != 'en_US') {
725 $i18n = CRM_Core_I18n::singleton();
726 $i18n->localizeArray(self::$stateProvince, array(
727 'context' => 'province',
728 ));
729 self::$stateProvince = CRM_Utils_Array::asort(self::$stateProvince);
730 }
731 }
732 if ($id) {
733 if (array_key_exists($id, self::$stateProvince)) {
734 return self::$stateProvince[$id];
735 }
736 else {
737 $result = NULL;
738 return $result;
739 }
740 }
741 return self::$stateProvince;
742 }
743
744 /**
745 * Get all the State/Province abbreviations from the database.
746 *
747 * Same as above, except gets the abbreviations instead of the names.
748 *
749 * @access public
750 * @static
751 *
752 * @param int $id - Optional id to return
753 *
754 * @return array - array reference of all State/Province abbreviations.
755 */
756 public static function &stateProvinceAbbreviation($id = FALSE, $limit = TRUE) {
757 if ($id > 1) {
758 $query = "
759 SELECT abbreviation
760 FROM civicrm_state_province
761 WHERE id = %1";
762 $params = array(
763 1 => array(
764 $id,
765 'Integer',
766 ),
767 );
768 return CRM_Core_DAO::singleValueQuery($query, $params);
769 }
770
771 if (!self::$stateProvinceAbbreviation || !$id) {
772
773 $whereClause = FALSE;
774
775 if ($limit) {
776 $config = CRM_Core_Config::singleton();
777 $countryIsoCodes = self::countryIsoCode();
778 $limitCodes = $config->provinceLimit();
779 $limitIds = array();
780 foreach ($limitCodes as $code) {
781 $tmpArray = array_keys($countryIsoCodes, $code);
782
783 if (!empty($tmpArray)) {
784 $limitIds[] = array_shift($tmpArray);
785 }
786 }
787 if (!empty($limitIds)) {
788 $whereClause = 'country_id IN (' . implode(', ', $limitIds) . ')';
789 }
790 }
791 self::populate(self::$stateProvinceAbbreviation, 'CRM_Core_DAO_StateProvince', TRUE, 'abbreviation', 'is_active', $whereClause);
792 }
793
794 if ($id) {
795 if (array_key_exists($id, self::$stateProvinceAbbreviation)) {
796 return self::$stateProvinceAbbreviation[$id];
797 }
798 else {
799 $result = NULL;
800 return $result;
801 }
802 }
803 return self::$stateProvinceAbbreviation;
804 }
805
806 /**
807 * Get all the countries from database.
808 *
809 * The static array country is returned, and if it's
810 * called the first time, the <b>Country DAO</b> is used
811 * to get all the countries.
812 *
813 * Note: any database errors will be trapped by the DAO.
814 *
815 * @access public
816 * @static
817 *
818 * @param int $id - Optional id to return
819 *
820 * @return array - array reference of all countries.
821 *
822 */
823 public static function country($id = FALSE, $applyLimit = TRUE) {
824 if (($id && !CRM_Utils_Array::value($id, self::$country)) || !self::$country || !$id) {
825
826 $config = CRM_Core_Config::singleton();
827 $limitCodes = array();
828
829 if ($applyLimit) {
830 // limit the country list to the countries specified in CIVICRM_COUNTRY_LIMIT
831 // (ensuring it's a subset of the legal values)
832 // K/P: We need to fix this, i dont think it works with new setting files
833 $limitCodes = $config->countryLimit();
834 if (!is_array($limitCodes)) {
835 $limitCodes = array(
836 $config->countryLimit => 1,
837 );
838 }
839
840 $limitCodes = array_intersect(self::countryIsoCode(), $limitCodes);
841 }
842
843 if (count($limitCodes)) {
844 $whereClause = "iso_code IN ('" . implode("', '", $limitCodes) . "')";
845 }
846 else {
847 $whereClause = NULL;
848 }
849
850 self::populate(self::$country, 'CRM_Core_DAO_Country', TRUE, 'name', 'is_active', $whereClause);
851
852 // if default country is set, percolate it to the top
853 if ($config->defaultContactCountry()) {
854 $countryIsoCodes = self::countryIsoCode();
855 $defaultID = array_search($config->defaultContactCountry(), $countryIsoCodes);
856 if ($defaultID !== FALSE) {
857 $default[$defaultID] = CRM_Utils_Array::value($defaultID, self::$country);
858 self::$country = $default + self::$country;
859 }
860 }
861
862 // localise the country names if in an non-en_US locale
863 global $tsLocale;
864 if ($tsLocale != '' and $tsLocale != 'en_US') {
865 $i18n = CRM_Core_I18n::singleton();
866 $i18n->localizeArray(self::$country, array(
867 'context' => 'country',
868 ));
869 self::$country = CRM_Utils_Array::asort(self::$country);
870 }
871 }
872 if ($id) {
873 if (array_key_exists($id, self::$country)) {
874 return self::$country[$id];
875 }
876 else {
877 return CRM_Core_DAO::$_nullObject;
878 }
879 }
880 return self::$country;
881 }
882
883 /**
884 * Get all the country ISO Code abbreviations from the database.
885 *
886 * The static array countryIsoCode is returned, and if it's
887 * called the first time, the <b>Country DAO</b> is used
888 * to get all the countries' ISO codes.
889 *
890 * Note: any database errors will be trapped by the DAO.
891 *
892 * @access public
893 * @static
894 *
895 * @return array - array reference of all country ISO codes.
896 *
897 */
898 public static function &countryIsoCode($id = FALSE) {
899 if (!self::$countryIsoCode) {
900 self::populate(self::$countryIsoCode, 'CRM_Core_DAO_Country', TRUE, 'iso_code');
901 }
902 if ($id) {
903 if (array_key_exists($id, self::$countryIsoCode)) {
904 return self::$countryIsoCode[$id];
905 }
906 else {
907 return CRM_Core_DAO::$_nullObject;
908 }
909 }
910 return self::$countryIsoCode;
911 }
912
913 /**
914 * DEPRECATED. Please use the buildOptions() method in the appropriate BAO object.
915 *
916 * Get all groups from database
917 *
918 * The static array group is returned, and if it's
919 * called the first time, the <b>Group DAO</b> is used
920 * to get all the groups.
921 *
922 * Note: any database errors will be trapped by the DAO.
923 *
924 * @param string $groupType type of group(Access/Mailing)
925 * @param boolen $excludeHidden exclude hidden groups.
926 *
927 * @access public
928 * @static
929 *
930 * @return array - array reference of all groups.
931 *
932 */
933 public static function &allGroup($groupType = NULL, $excludeHidden = TRUE) {
934 $condition = CRM_Contact_BAO_Group::groupTypeCondition($groupType, $excludeHidden);
935
936 if (!self::$group) {
937 self::$group = array();
938 }
939
940 $groupKey = $groupType ? $groupType : 'null';
941
942 if (!isset(self::$group[$groupKey])) {
943 self::$group[$groupKey] = NULL;
944 self::populate(self::$group[$groupKey], 'CRM_Contact_DAO_Group', FALSE, 'title', 'is_active', $condition);
945 }
946 return self::$group[$groupKey];
947 }
948
949 /**
950 * Create or get groups iterator (iterates over nested groups in a
951 * logical fashion)
952 *
953 * The GroupNesting instance is returned; it's created if this is being
954 * called for the first time
955 *
956 *
957 * @access public
958 * @static
959 *
960 * @return mixed - instance of CRM_Contact_BAO_GroupNesting
961 *
962 */
963 public static function &groupIterator($styledLabels = FALSE) {
964 if (!self::$groupIterator) {
965 /*
966 When used as an object, GroupNesting implements Iterator
967 and iterates nested groups in a logical manner for us
968 */
969 self::$groupIterator = new CRM_Contact_BAO_GroupNesting($styledLabels);
970 }
971 return self::$groupIterator;
972 }
973
974 /**
975 * DEPRECATED. Please use the buildOptions() method in the appropriate BAO object.
976 *
977 * Get all permissioned groups from database
978 *
979 * The static array group is returned, and if it's
980 * called the first time, the <b>Group DAO</b> is used
981 * to get all the groups.
982 *
983 * Note: any database errors will be trapped by the DAO.
984 *
985 * @param string $groupType type of group(Access/Mailing)
986 * @param boolen $excludeHidden exclude hidden groups.
987
988 * @access public
989 * @static
990 *
991 * @return array - array reference of all groups.
992 *
993 */
994 public static function group($groupType = NULL, $excludeHidden = TRUE) {
995 return CRM_Core_Permission::group($groupType, $excludeHidden);
996 }
997
998 /**
999 * Get all permissioned groups from database
1000 *
1001 * The static array group is returned, and if it's
1002 * called the first time, the <b>Group DAO</b> is used
1003 * to get all the groups.
1004 *
1005 * Note: any database errors will be trapped by the DAO.
1006 *
1007 * @access public
1008 * @static
1009 *
1010 * @return array - array reference of all groups.
1011 *
1012 */
1013 public static function &staticGroup($onlyPublic = FALSE, $groupType = NULL, $excludeHidden = TRUE) {
1014 if (!self::$staticGroup) {
1015 $condition = 'saved_search_id = 0 OR saved_search_id IS NULL';
1016 if ($onlyPublic) {
1017 $condition .= " AND visibility != 'User and User Admin Only'";
1018 }
1019
1020 if ($groupType) {
1021 $condition .= ' AND ' . CRM_Contact_BAO_Group::groupTypeCondition($groupType);
1022 }
1023
1024 if ($excludeHidden) {
1025 $condition .= ' AND is_hidden != 1 ';
1026 }
1027
1028 self::populate(self::$staticGroup, 'CRM_Contact_DAO_Group', FALSE, 'title', 'is_active', $condition, 'title');
1029 }
1030
1031 return self::$staticGroup;
1032 }
1033
1034 /**
1035 * Get all Relationship Types from database.
1036 *
1037 * The static array group is returned, and if it's
1038 * called the first time, the <b>RelationshipType DAO</b> is used
1039 * to get all the relationship types.
1040 *
1041 * Note: any database errors will be trapped by the DAO.
1042 *
1043 * @param string $valueColumnName db column name/label.
1044 * @param boolean $reset reset relationship types if true
1045 *
1046 * @access public
1047 * @static
1048 *
1049 * @return array - array reference of all relationship types.
1050 */
1051 public static function &relationshipType($valueColumnName = 'label', $reset = FALSE) {
1052 if (!CRM_Utils_Array::value($valueColumnName, self::$relationshipType) || $reset) {
1053 self::$relationshipType[$valueColumnName] = array();
1054
1055 //now we have name/label columns CRM-3336
1056 $column_a_b = "{$valueColumnName}_a_b";
1057 $column_b_a = "{$valueColumnName}_b_a";
1058
1059 $relationshipTypeDAO = new CRM_Contact_DAO_RelationshipType();
1060 $relationshipTypeDAO->selectAdd();
1061 $relationshipTypeDAO->selectAdd("id, {$column_a_b}, {$column_b_a}, contact_type_a, contact_type_b, contact_sub_type_a, contact_sub_type_b");
1062 $relationshipTypeDAO->is_active = 1;
1063 $relationshipTypeDAO->find();
1064 while ($relationshipTypeDAO->fetch()) {
1065
1066 self::$relationshipType[$valueColumnName][$relationshipTypeDAO->id] = array(
1067 'id' => $relationshipTypeDAO->id,
1068 $column_a_b => $relationshipTypeDAO->$column_a_b,
1069 $column_b_a => $relationshipTypeDAO->$column_b_a,
1070 'contact_type_a' => "$relationshipTypeDAO->contact_type_a",
1071 'contact_type_b' => "$relationshipTypeDAO->contact_type_b",
1072 'contact_sub_type_a' => "$relationshipTypeDAO->contact_sub_type_a",
1073 'contact_sub_type_b' => "$relationshipTypeDAO->contact_sub_type_b",
1074 );
1075 }
1076 }
1077
1078 return self::$relationshipType[$valueColumnName];
1079 }
1080
1081 /**
1082 * get all the ISO 4217 currency codes
1083 *
1084 * so far, we use this for validation only, so there's no point of putting this into the database
1085 *
1086 * @access public
1087 *
1088 * @return array - array reference of all currency codes
1089 * @static
1090 */
1091 public static function &currencyCode() {
1092 if (!self::$currencyCode) {
1093 self::$currencyCode = array(
1094 'AFN',
1095 'ALL',
1096 'DZD',
1097 'USD',
1098 'EUR',
1099 'AOA',
1100 'XCD',
1101 'XCD',
1102 'ARS',
1103 'AMD',
1104 'AWG',
1105 'AUD',
1106 'EUR',
1107 'AZM',
1108 'BSD',
1109 'BHD',
1110 'BDT',
1111 'BBD',
1112 'BYR',
1113 'EUR',
1114 'BZD',
1115 'XOF',
1116 'BMD',
1117 'INR',
1118 'BTN',
1119 'BOB',
1120 'BOV',
1121 'BAM',
1122 'BWP',
1123 'NOK',
1124 'BRL',
1125 'USD',
1126 'BND',
1127 'BGN',
1128 'XOF',
1129 'BIF',
1130 'KHR',
1131 'XAF',
1132 'CAD',
1133 'CVE',
1134 'KYD',
1135 'XAF',
1136 'XAF',
1137 'CLP',
1138 'CLF',
1139 'CNY',
1140 'AUD',
1141 'AUD',
1142 'COP',
1143 'COU',
1144 'KMF',
1145 'XAF',
1146 'CDF',
1147 'NZD',
1148 'CRC',
1149 'XOF',
1150 'HRK',
1151 'CUP',
1152 'CYP',
1153 'CZK',
1154 'DKK',
1155 'DJF',
1156 'XCD',
1157 'DOP',
1158 'USD',
1159 'EGP',
1160 'SVC',
1161 'USD',
1162 'XAF',
1163 'ERN',
1164 'EEK',
1165 'ETB',
1166 'FKP',
1167 'DKK',
1168 'FJD',
1169 'EUR',
1170 'EUR',
1171 'EUR',
1172 'XPF',
1173 'EUR',
1174 'XAF',
1175 'GMD',
1176 'GEL',
1177 'EUR',
1178 'GHC',
1179 'GIP',
1180 'EUR',
1181 'DKK',
1182 'XCD',
1183 'EUR',
1184 'USD',
1185 'GTQ',
1186 'GNF',
1187 'GWP',
1188 'XOF',
1189 'GYD',
1190 'HTG',
1191 'USD',
1192 'AUD',
1193 'EUR',
1194 'HNL',
1195 'HKD',
1196 'HUF',
1197 'ISK',
1198 'INR',
1199 'IDR',
1200 'XDR',
1201 'IRR',
1202 'IQD',
1203 'EUR',
1204 'ILS',
1205 'EUR',
1206 'JMD',
1207 'JPY',
1208 'JOD',
1209 'KZT',
1210 'KES',
1211 'AUD',
1212 'KPW',
1213 'KRW',
1214 'KWD',
1215 'KGS',
1216 'LAK',
1217 'LVL',
1218 'LBP',
1219 'ZAR',
1220 'LSL',
1221 'LRD',
1222 'LYD',
1223 'CHF',
1224 'LTL',
1225 'EUR',
1226 'MOP',
1227 'MKD',
1228 'MGA',
1229 'MWK',
1230 'MYR',
1231 'MVR',
1232 'XOF',
1233 'MTL',
1234 'USD',
1235 'EUR',
1236 'MRO',
1237 'MUR',
1238 'EUR',
1239 'MXN',
1240 'MXV',
1241 'USD',
1242 'MDL',
1243 'EUR',
1244 'MNT',
1245 'XCD',
1246 'MAD',
1247 'MZM',
1248 'MMK',
1249 'ZAR',
1250 'NAD',
1251 'AUD',
1252 'NPR',
1253 'EUR',
1254 'ANG',
1255 'XPF',
1256 'NZD',
1257 'NIO',
1258 'XOF',
1259 'NGN',
1260 'NZD',
1261 'AUD',
1262 'USD',
1263 'NOK',
1264 'OMR',
1265 'PKR',
1266 'USD',
1267 'PAB',
1268 'USD',
1269 'PGK',
1270 'PYG',
1271 'PEN',
1272 'PHP',
1273 'NZD',
1274 'PLN',
1275 'EUR',
1276 'USD',
1277 'QAR',
1278 'EUR',
1279 'ROL',
1280 'RON',
1281 'RUB',
1282 'RWF',
1283 'SHP',
1284 'XCD',
1285 'XCD',
1286 'EUR',
1287 'XCD',
1288 'WST',
1289 'EUR',
1290 'STD',
1291 'SAR',
1292 'XOF',
1293 'CSD',
1294 'EUR',
1295 'SCR',
1296 'SLL',
1297 'SGD',
1298 'SKK',
1299 'SIT',
1300 'SBD',
1301 'SOS',
1302 'ZAR',
1303 'EUR',
1304 'LKR',
1305 'SDD',
1306 'SRD',
1307 'NOK',
1308 'SZL',
1309 'SEK',
1310 'CHF',
1311 'CHW',
1312 'CHE',
1313 'SYP',
1314 'TWD',
1315 'TJS',
1316 'TZS',
1317 'THB',
1318 'USD',
1319 'XOF',
1320 'NZD',
1321 'TOP',
1322 'TTD',
1323 'TND',
1324 'TRY',
1325 'TRL',
1326 'TMM',
1327 'USD',
1328 'AUD',
1329 'UGX',
1330 'UAH',
1331 'AED',
1332 'GBP',
1333 'USD',
1334 'USS',
1335 'USN',
1336 'USD',
1337 'UYU',
1338 'UZS',
1339 'VUV',
1340 'VEB',
1341 'VND',
1342 'USD',
1343 'USD',
1344 'XPF',
1345 'MAD',
1346 'YER',
1347 'ZMK',
1348 'ZWD',
1349 'XAU',
1350 'XBA',
1351 'XBB',
1352 'XBC',
1353 'XBD',
1354 'XPD',
1355 'XPT',
1356 'XAG',
1357 'XFU',
1358 'XFO',
1359 'XTS',
1360 'XXX',
1361 );
1362 }
1363 return self::$currencyCode;
1364 }
1365
1366 /**
1367 * Get all the County from database.
1368 *
1369 * The static array county is returned, and if it's
1370 * called the first time, the <b>County DAO</b> is used
1371 * to get all the Counties.
1372 *
1373 * Note: any database errors will be trapped by the DAO.
1374 *
1375 * @access public
1376 * @static
1377 *
1378 * @param int $id - Optional id to return
1379 *
1380 * @return array - array reference of all Counties
1381 *
1382 */
1383 public static function &county($id = FALSE) {
1384 if (!self::$county) {
1385
1386 $config = CRM_Core_Config::singleton();
1387 // order by id so users who populate civicrm_county can have more control over sort by the order they load the counties
1388 self::populate(self::$county, 'CRM_Core_DAO_County', TRUE, 'name', NULL, NULL, 'id');
1389 }
1390 if ($id) {
1391 if (array_key_exists($id, self::$county)) {
1392 return self::$county[$id];
1393 }
1394 else {
1395 return CRM_Core_DAO::$_nullObject;
1396 }
1397 }
1398 return self::$county;
1399 }
1400
1401 /**
1402 * DEPRECATED. Please use the buildOptions() method in the appropriate BAO object.
1403 * Get all active payment processors
1404 *
1405 * The static array paymentProcessor is returned
1406 *
1407 * @access public
1408 * @static
1409 *
1410 * @param boolean $all - get payment processors - default is to get only active ones.
1411 * @param boolean $test - get test payment processors
1412 *
1413 * @return array - array of all payment processors
1414 *
1415 */
1416 public static function &paymentProcessor($all = FALSE, $test = FALSE, $additionalCond = NULL) {
1417 $condition = "is_test = ";
1418 $condition .= ($test) ? '1' : '0';
1419
1420 if ($additionalCond) {
1421 $condition .= " AND ( $additionalCond ) ";
1422 }
1423
1424 // CRM-7178. Make sure we only include payment processors valid in ths
1425 // domain
1426 $condition .= " AND domain_id = " . CRM_Core_Config::domainID();
1427
1428 $cacheKey = $condition . '_' . (int) $all;
1429 if (!isset(self::$paymentProcessor[$cacheKey])) {
1430 self::populate(self::$paymentProcessor[$cacheKey], 'CRM_Financial_DAO_PaymentProcessor', $all, 'name', 'is_active', $condition, 'is_default desc, name');
1431 }
1432
1433 return self::$paymentProcessor[$cacheKey];
1434 }
1435
1436 /**
1437 * DEPRECATED. Please use the buildOptions() method in the appropriate BAO object.
1438 *
1439 * The static array paymentProcessorType is returned
1440 *
1441 * @access public
1442 * @static
1443 *
1444 * @param boolean $all - get payment processors - default is to get only active ones.
1445 *
1446 * @return array - array of all payment processor types
1447 *
1448 */
1449 public static function &paymentProcessorType($all = FALSE, $id = NULL, $return = 'title') {
1450 $cacheKey = $id . '_' .$return;
1451 if (empty(self::$paymentProcessorType[$cacheKey])) {
1452 self::populate(self::$paymentProcessorType[$cacheKey], 'CRM_Financial_DAO_PaymentProcessorType', $all, $return, 'is_active', NULL, "is_default, $return", 'id');
1453 }
1454 if ($id && CRM_Utils_Array::value($id, self::$paymentProcessorType[$cacheKey])) {
1455 return self::$paymentProcessorType[$cacheKey][$id];
1456 }
1457 return self::$paymentProcessorType[$cacheKey];
1458 }
1459
1460 /**
1461 * Get all the World Regions from Database
1462 *
1463 * @access public
1464 *
1465 * @return array - array reference of all World Regions
1466 * @static
1467 */
1468 public static function &worldRegion($id = FALSE) {
1469 if (!self::$worldRegions) {
1470 self::populate(self::$worldRegions, 'CRM_Core_DAO_Worldregion', TRUE, 'name', NULL, NULL, 'id');
1471 }
1472
1473 if ($id) {
1474 if (array_key_exists($id, self::$worldRegions)) {
1475 return self::$worldRegions[$id];
1476 }
1477 else {
1478 return CRM_Core_DAO::$_nullObject;
1479 }
1480 }
1481
1482 return self::$worldRegions;
1483 }
1484
1485 /**
1486 * DEPRECATED. Please use the buildOptions() method in the appropriate BAO object.
1487 *
1488 * Get all Activity Statuses.
1489 *
1490 * The static array activityStatus is returned
1491 *
1492 * @access public
1493 * @static
1494 *
1495 * @return array - array reference of all activity statuses
1496 */
1497 public static function &activityStatus($column = 'label') {
1498 if (NULL === self::$activityStatus) {
1499 self::$activityStatus = array();
1500 }
1501 if (!array_key_exists($column, self::$activityStatus)) {
1502 self::$activityStatus[$column] = array();
1503
1504 self::$activityStatus[$column] = CRM_Core_OptionGroup::values('activity_status', FALSE, FALSE, FALSE, NULL, $column);
1505 }
1506
1507 return self::$activityStatus[$column];
1508 }
1509
1510 /**
1511 * DEPRECATED. Please use the buildOptions() method in the appropriate BAO object.
1512 *
1513 * Get all Visibility levels.
1514 *
1515 * The static array visibility is returned
1516 *
1517 * @access public
1518 * @static
1519 *
1520 * @return array - array reference of all Visibility levels.
1521 *
1522 */
1523 public static function &visibility($column = 'label') {
1524 if (!isset(self::$visibility)) {
1525 self::$visibility = array( );
1526 }
1527
1528 if (!isset(self::$visibility[$column])) {
1529 self::$visibility[$column] = CRM_Core_OptionGroup::values('visibility', FALSE, FALSE, FALSE, NULL, $column);
1530 }
1531
1532 return self::$visibility[$column];
1533 }
1534
1535 public static function &stateProvinceForCountry($countryID, $field = 'name') {
1536 static $_cache = NULL;
1537
1538 $cacheKey = "{$countryID}_{$field}";
1539 if (!$_cache) {
1540 $_cache = array();
1541 }
1542
1543 if (!empty($_cache[$cacheKey])) {
1544 return $_cache[$cacheKey];
1545 }
1546
1547 $query = "
1548 SELECT civicrm_state_province.{$field} name, civicrm_state_province.id id
1549 FROM civicrm_state_province
1550 WHERE country_id = %1
1551 ORDER BY name";
1552 $params = array(
1553 1 => array(
1554 $countryID,
1555 'Integer',
1556 ),
1557 );
1558
1559 $dao = CRM_Core_DAO::executeQuery($query, $params);
1560
1561 $result = array();
1562 while ($dao->fetch()) {
1563 $result[$dao->id] = $dao->name;
1564 }
1565
1566 // localise the stateProvince names if in an non-en_US locale
1567 $config = CRM_Core_Config::singleton();
1568 global $tsLocale;
1569 if ($tsLocale != '' and $tsLocale != 'en_US') {
1570 $i18n = CRM_Core_I18n::singleton();
1571 $i18n->localizeArray($result, array(
1572 'context' => 'province',
1573 ));
1574 $result = CRM_Utils_Array::asort($result);
1575 }
1576
1577 $_cache[$cacheKey] = $result;
1578
1579 CRM_Utils_Hook::buildStateProvinceForCountry($countryID, $result);
1580
1581 return $result;
1582 }
1583
1584 public static function &countyForState($stateID) {
1585 if (is_array($stateID)) {
1586 $states = implode(", ", $stateID);
1587 $query = "
1588 SELECT civicrm_county.name name, civicrm_county.id id, civicrm_state_province.abbreviation abbreviation
1589 FROM civicrm_county
1590 LEFT JOIN civicrm_state_province ON civicrm_county.state_province_id = civicrm_state_province.id
1591 WHERE civicrm_county.state_province_id in ( $states )
1592 ORDER BY civicrm_state_province.abbreviation, civicrm_county.name";
1593
1594 $dao = CRM_Core_DAO::executeQuery($query);
1595
1596 $result = array();
1597 while ($dao->fetch()) {
1598 $result[$dao->id] = $dao->abbreviation . ': ' . $dao->name;
1599 }
1600 }
1601 else {
1602
1603 static $_cache = NULL;
1604
1605 $cacheKey = "{$stateID}_name";
1606 if (!$_cache) {
1607 $_cache = array();
1608 }
1609
1610 if (!empty($_cache[$cacheKey])) {
1611 return $_cache[$cacheKey];
1612 }
1613
1614 $query = "
1615 SELECT civicrm_county.name name, civicrm_county.id id
1616 FROM civicrm_county
1617 WHERE state_province_id = %1
1618 ORDER BY name";
1619 $params = array(
1620 1 => array(
1621 $stateID,
1622 'Integer',
1623 ),
1624 );
1625
1626 $dao = CRM_Core_DAO::executeQuery($query, $params);
1627
1628 $result = array();
1629 while ($dao->fetch()) {
1630 $result[$dao->id] = $dao->name;
1631 }
1632 }
1633
1634 return $result;
1635 }
1636
1637 /**
1638 * Given a state ID return the country ID, this allows
1639 * us to populate forms and values for downstream code
1640 *
1641 * @param $stateID int
1642 *
1643 * @return int the country id that the state belongs to
1644 * @static
1645 * @public
1646 */
1647 static function countryIDForStateID($stateID) {
1648 if (empty($stateID)) {
1649 return CRM_Core_DAO::$_nullObject;
1650 }
1651
1652 $query = "
1653 SELECT country_id
1654 FROM civicrm_state_province
1655 WHERE id = %1
1656 ";
1657 $params = array(1 => array($stateID, 'Integer'));
1658
1659 return CRM_Core_DAO::singleValueQuery($query, $params);
1660 }
1661
1662 /**
1663 * Get all types of Greetings.
1664 *
1665 * The static array of greeting is returned
1666 *
1667 * @access public
1668 * @static
1669 *
1670 * @param $filter - get All Email Greetings - default is to get only active ones.
1671 *
1672 * @return array - array reference of all greetings.
1673 *
1674 */
1675 public static function greeting($filter, $columnName = 'label') {
1676 $index = $filter['greeting_type'] . '_' . $columnName;
1677
1678 // also add contactType to the array
1679 $contactType = CRM_Utils_Array::value('contact_type', $filter);
1680 if ($contactType) {
1681 $index .= '_' . $contactType;
1682 }
1683
1684 if (NULL === self::$greeting) {
1685 self::$greeting = array();
1686 }
1687
1688 if (!CRM_Utils_Array::value($index, self::$greeting)) {
1689 $filterCondition = NULL;
1690 if ($contactType) {
1691 $filterVal = 'v.filter =';
1692 switch ($contactType) {
1693 case 'Individual':
1694 $filterVal .= "1";
1695 break;
1696
1697 case 'Household':
1698 $filterVal .= "2";
1699 break;
1700
1701 case 'Organization':
1702 $filterVal .= "3";
1703 break;
1704 }
1705 $filterCondition .= "AND (v.filter = 0 OR {$filterVal}) ";
1706 }
1707
1708 self::$greeting[$index] = CRM_Core_OptionGroup::values($filter['greeting_type'], NULL, NULL, NULL, $filterCondition, $columnName);
1709 }
1710
1711 return self::$greeting[$index];
1712 }
1713
1714 /**
1715 * Construct array of default greeting values for contact type
1716 *
1717 * @access public
1718 * @static
1719 *
1720 * @return array - array reference of default greetings.
1721 *
1722 */
1723 public static function &greetingDefaults() {
1724 if (!self::$greetingDefaults) {
1725 $defaultGreetings = array();
1726 $contactTypes = self::get('CRM_Contact_DAO_Contact', 'contact_type', array('keyColumn' => 'id', 'labelColumn' => 'name'));
1727
1728 foreach ($contactTypes as $filter => $contactType) {
1729 $filterCondition = " AND (v.filter = 0 OR v.filter = $filter) AND v.is_default = 1 ";
1730
1731 foreach (CRM_Contact_BAO_Contact::$_greetingTypes as $greeting) {
1732 $tokenVal = CRM_Core_OptionGroup::values($greeting, NULL, NULL, NULL, $filterCondition, 'label');
1733 $defaultGreetings[$contactType][$greeting] = $tokenVal;
1734 }
1735 }
1736
1737 self::$greetingDefaults = $defaultGreetings;
1738 }
1739
1740 return self::$greetingDefaults;
1741 }
1742
1743 /**
1744 * Get all extensions
1745 *
1746 * The static array extensions
1747 *
1748 * FIXME: This is called by civix but not by any core code. We
1749 * should provide an API call which civix can use instead.
1750 *
1751 * @access public
1752 * @static
1753 *
1754 * @return array - array($fullyQualifiedName => $label) list of extensions
1755 */
1756 public static function &getExtensions() {
1757 if (!self::$extensions) {
1758 self::$extensions = array();
1759 $sql = '
1760 SELECT full_name, label
1761 FROM civicrm_extension
1762 WHERE is_active = 1
1763 ';
1764 $dao = CRM_Core_DAO::executeQuery($sql);
1765 while ($dao->fetch()) {
1766 self::$extensions[$dao->full_name] = $dao->label;
1767 }
1768 }
1769
1770 return self::$extensions;
1771 }
1772
1773 /**
1774 * Get all options values
1775 *
1776 * The static array option values is returned
1777 *
1778 * @access public
1779 * @static
1780 *
1781 * @param boolean $optionGroupName - get All Option Group values- default is to get only active ones.
1782 *
1783 * @return array - array reference of all Option Group Name
1784 *
1785 */
1786 public static function accountOptionValues($optionGroupName, $id = null, $condition = null) {
1787 $cacheKey = $optionGroupName . '_' . $condition;
1788 if (empty(self::$accountOptionValues[$cacheKey])) {
1789 self::$accountOptionValues[$cacheKey] = CRM_Core_OptionGroup::values($optionGroupName, false, false, false, $condition);
1790 }
1791 if ($id) {
1792 return CRM_Utils_Array::value($id, self::$accountOptionValues[$cacheKey]);
1793 }
1794
1795 return self::$accountOptionValues[$cacheKey];
1796 }
1797
1798 /**
1799 * Fetch the list of active extensions of type 'module'
1800 *
1801 * @param $fresh bool whether to forcibly reload extensions list from canonical store
1802 * @access public
1803 * @static
1804 *
1805 * @return array - array(array('prefix' => $, 'file' => $))
1806 */
1807 public static function getModuleExtensions($fresh = FALSE) {
1808 return CRM_Extension_System::singleton()->getMapper()->getActiveModuleFiles($fresh);
1809 }
1810 }
1811