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