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