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