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