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