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