Merge pull request #7969 from monishdeb/CRM-18224
[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 = array();
81
82 /**
83 * Country.
84 * @var array
85 */
86 private static $country;
87
88 /**
89 * CountryIsoCode.
90 * @var array
91 */
92 private static $countryIsoCode;
93
94 /**
95 * @deprecated Please use the buildOptions() method in the appropriate BAO object.
96 *
97 * group
98 * @var array
99 */
100 private static $group;
101
102 /**
103 * 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 && is_numeric($id)) {
742 if (!array_key_exists($id, (array) self::$stateProvinceAbbreviation)) {
743 $query = "SELECT abbreviation
744 FROM civicrm_state_province
745 WHERE id = %1";
746 $params = array(
747 1 => array(
748 $id,
749 'Integer',
750 ),
751 );
752 self::$stateProvinceAbbreviation[$id] = CRM_Core_DAO::singleValueQuery($query, $params);
753 }
754 return self::$stateProvinceAbbreviation[$id];
755 }
756 else {
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 return self::$stateProvinceAbbreviation;
778 }
779
780 /**
781 * Get all the countries from database.
782 *
783 * The static array country is returned, and if it's
784 * called the first time, the <b>Country DAO</b> is used
785 * to get all the countries.
786 *
787 * Note: any database errors will be trapped by the DAO.
788 *
789 *
790 * @param bool|int $id - Optional id to return
791 *
792 * @param bool $applyLimit
793 *
794 * @return array
795 * array reference of all countries.
796 */
797 public static function country($id = FALSE, $applyLimit = TRUE) {
798 if (($id && !CRM_Utils_Array::value($id, self::$country)) || !self::$country || !$id) {
799
800 $config = CRM_Core_Config::singleton();
801 $limitCodes = array();
802
803 if ($applyLimit) {
804 // limit the country list to the countries specified in CIVICRM_COUNTRY_LIMIT
805 // (ensuring it's a subset of the legal values)
806 // K/P: We need to fix this, i dont think it works with new setting files
807 $limitCodes = CRM_Core_BAO_Country::countryLimit();
808 if (!is_array($limitCodes)) {
809 $limitCodes = array(
810 $config->countryLimit => 1,
811 );
812 }
813
814 $limitCodes = array_intersect(self::countryIsoCode(), $limitCodes);
815 }
816
817 if (count($limitCodes)) {
818 $whereClause = "iso_code IN ('" . implode("', '", $limitCodes) . "')";
819 }
820 else {
821 $whereClause = NULL;
822 }
823
824 self::populate(self::$country, 'CRM_Core_DAO_Country', TRUE, 'name', 'is_active', $whereClause);
825
826 // if default country is set, percolate it to the top
827 if ($config->defaultContactCountry()) {
828 $countryIsoCodes = self::countryIsoCode();
829 $defaultID = array_search($config->defaultContactCountry(), $countryIsoCodes);
830 if ($defaultID !== FALSE) {
831 $default[$defaultID] = CRM_Utils_Array::value($defaultID, self::$country);
832 self::$country = $default + self::$country;
833 }
834 }
835
836 // localise the country names if in an non-en_US locale
837 global $tsLocale;
838 if ($tsLocale != '' and $tsLocale != 'en_US') {
839 $i18n = CRM_Core_I18n::singleton();
840 $i18n->localizeArray(self::$country, array(
841 'context' => 'country',
842 ));
843 self::$country = CRM_Utils_Array::asort(self::$country);
844 }
845 }
846 if ($id) {
847 if (array_key_exists($id, self::$country)) {
848 return self::$country[$id];
849 }
850 else {
851 return CRM_Core_DAO::$_nullObject;
852 }
853 }
854 return self::$country;
855 }
856
857 /**
858 * Get all the country ISO Code abbreviations from the database.
859 *
860 * The static array countryIsoCode is returned, and if it's
861 * called the first time, the <b>Country DAO</b> is used
862 * to get all the countries' ISO codes.
863 *
864 * Note: any database errors will be trapped by the DAO.
865 *
866 *
867 * @param bool $id
868 *
869 * @return array
870 * array reference of all country ISO codes.
871 */
872 public static function &countryIsoCode($id = FALSE) {
873 if (!self::$countryIsoCode) {
874 self::populate(self::$countryIsoCode, 'CRM_Core_DAO_Country', TRUE, 'iso_code');
875 }
876 if ($id) {
877 if (array_key_exists($id, self::$countryIsoCode)) {
878 return self::$countryIsoCode[$id];
879 }
880 else {
881 return CRM_Core_DAO::$_nullObject;
882 }
883 }
884 return self::$countryIsoCode;
885 }
886
887 /**
888 * @deprecated Please use the buildOptions() method in the appropriate BAO object.
889 *
890 * Get all groups from database
891 *
892 * The static array group is returned, and if it's
893 * called the first time, the <b>Group DAO</b> is used
894 * to get all the groups.
895 *
896 * Note: any database errors will be trapped by the DAO.
897 *
898 * @param string $groupType
899 * Type of group(Access/Mailing).
900 * @param bool $excludeHidden
901 * Exclude hidden groups.
902 *
903 *
904 * @return array
905 * array reference of all groups.
906 */
907 public static function allGroup($groupType = NULL, $excludeHidden = TRUE) {
908 $condition = CRM_Contact_BAO_Group::groupTypeCondition($groupType, $excludeHidden);
909
910 if (!self::$group) {
911 self::$group = array();
912 }
913
914 $groupKey = ($groupType ? $groupType : 'null') . !empty($excludeHidden);
915
916 if (!isset(self::$group[$groupKey])) {
917 self::$group[$groupKey] = NULL;
918 self::populate(self::$group[$groupKey], 'CRM_Contact_DAO_Group', FALSE, 'title', 'is_active', $condition);
919 }
920 return self::$group[$groupKey];
921 }
922
923 /**
924 * Create or get groups iterator (iterates over nested groups in a
925 * logical fashion)
926 *
927 * The GroupNesting instance is returned; it's created if this is being
928 * called for the first time
929 *
930 *
931 *
932 * @param bool $styledLabels
933 *
934 * @return CRM_Contact_BAO_GroupNesting
935 */
936 public static function &groupIterator($styledLabels = FALSE) {
937 if (!self::$groupIterator) {
938 // When used as an object, GroupNesting implements Iterator
939 // and iterates nested groups in a logical manner for us
940 self::$groupIterator = new CRM_Contact_BAO_GroupNesting($styledLabels);
941 }
942 return self::$groupIterator;
943 }
944
945 /**
946 * Get all permissioned groups from database.
947 *
948 * The static array group is returned, and if it's
949 * called the first time, the <b>Group DAO</b> is used
950 * to get all the groups.
951 *
952 * Note: any database errors will be trapped by the DAO.
953 *
954 * @param string $groupType
955 * Type of group(Access/Mailing).
956 * @param bool $excludeHidden
957 * Exclude hidden groups.
958 *
959 *
960 * @return array
961 * array reference of all groups.
962 */
963 public static function group($groupType = NULL, $excludeHidden = TRUE) {
964 return CRM_Core_Permission::group($groupType, $excludeHidden);
965 }
966
967 /**
968 * Fetch groups in a nested format suitable for use in select form element.
969 * @param bool $checkPermissions
970 * @param string|null $groupType
971 * @param bool $excludeHidden
972 * @return array
973 */
974 public static function nestedGroup($checkPermissions = TRUE, $groupType = NULL, $excludeHidden = TRUE) {
975 $groups = $checkPermissions ? self::group($groupType, $excludeHidden) : self::allGroup($groupType, $excludeHidden);
976 return CRM_Contact_BAO_Group::getGroupsHierarchy($groups, NULL, '&nbsp;&nbsp;', TRUE);
977 }
978
979 /**
980 * Get all permissioned groups from database.
981 *
982 * The static array group is returned, and if it's
983 * called the first time, the <b>Group DAO</b> is used
984 * to get all the groups.
985 *
986 * Note: any database errors will be trapped by the DAO.
987 *
988 *
989 * @param bool $onlyPublic
990 * @param null $groupType
991 * @param bool $excludeHidden
992 *
993 * @return array
994 * array reference of all groups.
995 */
996 public static function &staticGroup($onlyPublic = FALSE, $groupType = NULL, $excludeHidden = TRUE) {
997 if (!self::$staticGroup) {
998 $condition = 'saved_search_id = 0 OR saved_search_id IS NULL';
999 if ($onlyPublic) {
1000 $condition .= " AND visibility != 'User and User Admin Only'";
1001 }
1002
1003 if ($groupType) {
1004 $condition .= ' AND ' . CRM_Contact_BAO_Group::groupTypeCondition($groupType);
1005 }
1006
1007 if ($excludeHidden) {
1008 $condition .= ' AND is_hidden != 1 ';
1009 }
1010
1011 self::populate(self::$staticGroup, 'CRM_Contact_DAO_Group', FALSE, 'title', 'is_active', $condition, 'title');
1012 }
1013
1014 return self::$staticGroup;
1015 }
1016
1017 /**
1018 * Get all Relationship Types from database.
1019 *
1020 * The static array group is returned, and if it's
1021 * called the first time, the <b>RelationshipType DAO</b> is used
1022 * to get all the relationship types.
1023 *
1024 * Note: any database errors will be trapped by the DAO.
1025 *
1026 * @param string $valueColumnName
1027 * Db column name/label.
1028 * @param bool $reset
1029 * Reset relationship types if true.
1030 * @param bool|NULL $isActive
1031 * Filter by is_active. NULL to disable.
1032 *
1033 * @return array
1034 * array reference of all relationship types.
1035 */
1036 public static function &relationshipType($valueColumnName = 'label', $reset = FALSE, $isActive = 1) {
1037 $cacheKey = $valueColumnName . '::' . $isActive;
1038 if (!CRM_Utils_Array::value($cacheKey, self::$relationshipType) || $reset) {
1039 self::$relationshipType[$cacheKey] = array();
1040
1041 //now we have name/label columns CRM-3336
1042 $column_a_b = "{$valueColumnName}_a_b";
1043 $column_b_a = "{$valueColumnName}_b_a";
1044
1045 $relationshipTypeDAO = new CRM_Contact_DAO_RelationshipType();
1046 $relationshipTypeDAO->selectAdd();
1047 $relationshipTypeDAO->selectAdd("id, {$column_a_b}, {$column_b_a}, contact_type_a, contact_type_b, contact_sub_type_a, contact_sub_type_b");
1048 if ($isActive !== NULL) {
1049 $relationshipTypeDAO->is_active = $isActive;
1050 }
1051 $relationshipTypeDAO->find();
1052 while ($relationshipTypeDAO->fetch()) {
1053
1054 self::$relationshipType[$cacheKey][$relationshipTypeDAO->id] = array(
1055 'id' => $relationshipTypeDAO->id,
1056 $column_a_b => $relationshipTypeDAO->$column_a_b,
1057 $column_b_a => $relationshipTypeDAO->$column_b_a,
1058 'contact_type_a' => "$relationshipTypeDAO->contact_type_a",
1059 'contact_type_b' => "$relationshipTypeDAO->contact_type_b",
1060 'contact_sub_type_a' => "$relationshipTypeDAO->contact_sub_type_a",
1061 'contact_sub_type_b' => "$relationshipTypeDAO->contact_sub_type_b",
1062 );
1063 }
1064 }
1065
1066 return self::$relationshipType[$cacheKey];
1067 }
1068
1069 /**
1070 * Get all the ISO 4217 currency codes
1071 *
1072 * so far, we use this for validation only, so there's no point of putting this into the database
1073 *
1074 *
1075 * @return array
1076 * array reference of all currency codes
1077 */
1078 public static function &currencyCode() {
1079 if (!self::$currencyCode) {
1080 self::$currencyCode = array(
1081 'AFN',
1082 'ALL',
1083 'DZD',
1084 'USD',
1085 'EUR',
1086 'AOA',
1087 'XCD',
1088 'XCD',
1089 'ARS',
1090 'AMD',
1091 'AWG',
1092 'AUD',
1093 'EUR',
1094 'AZM',
1095 'BSD',
1096 'BHD',
1097 'BDT',
1098 'BBD',
1099 'BYR',
1100 'EUR',
1101 'BZD',
1102 'XOF',
1103 'BMD',
1104 'INR',
1105 'BTN',
1106 'BOB',
1107 'BOV',
1108 'BAM',
1109 'BWP',
1110 'NOK',
1111 'BRL',
1112 'USD',
1113 'BND',
1114 'BGN',
1115 'XOF',
1116 'BIF',
1117 'KHR',
1118 'XAF',
1119 'CAD',
1120 'CVE',
1121 'KYD',
1122 'XAF',
1123 'XAF',
1124 'CLP',
1125 'CLF',
1126 'CNY',
1127 'AUD',
1128 'AUD',
1129 'COP',
1130 'COU',
1131 'KMF',
1132 'XAF',
1133 'CDF',
1134 'NZD',
1135 'CRC',
1136 'XOF',
1137 'HRK',
1138 'CUP',
1139 'CYP',
1140 'CZK',
1141 'DKK',
1142 'DJF',
1143 'XCD',
1144 'DOP',
1145 'USD',
1146 'EGP',
1147 'SVC',
1148 'USD',
1149 'XAF',
1150 'ERN',
1151 'EEK',
1152 'ETB',
1153 'FKP',
1154 'DKK',
1155 'FJD',
1156 'EUR',
1157 'EUR',
1158 'EUR',
1159 'XPF',
1160 'EUR',
1161 'XAF',
1162 'GMD',
1163 'GEL',
1164 'EUR',
1165 'GHC',
1166 'GIP',
1167 'EUR',
1168 'DKK',
1169 'XCD',
1170 'EUR',
1171 'USD',
1172 'GTQ',
1173 'GNF',
1174 'GWP',
1175 'XOF',
1176 'GYD',
1177 'HTG',
1178 'USD',
1179 'AUD',
1180 'EUR',
1181 'HNL',
1182 'HKD',
1183 'HUF',
1184 'ISK',
1185 'INR',
1186 'IDR',
1187 'XDR',
1188 'IRR',
1189 'IQD',
1190 'EUR',
1191 'ILS',
1192 'EUR',
1193 'JMD',
1194 'JPY',
1195 'JOD',
1196 'KZT',
1197 'KES',
1198 'AUD',
1199 'KPW',
1200 'KRW',
1201 'KWD',
1202 'KGS',
1203 'LAK',
1204 'LVL',
1205 'LBP',
1206 'ZAR',
1207 'LSL',
1208 'LRD',
1209 'LYD',
1210 'CHF',
1211 'LTL',
1212 'EUR',
1213 'MOP',
1214 'MKD',
1215 'MGA',
1216 'MWK',
1217 'MYR',
1218 'MVR',
1219 'XOF',
1220 'MTL',
1221 'USD',
1222 'EUR',
1223 'MRO',
1224 'MUR',
1225 'EUR',
1226 'MXN',
1227 'MXV',
1228 'USD',
1229 'MDL',
1230 'EUR',
1231 'MNT',
1232 'XCD',
1233 'MAD',
1234 'MZM',
1235 'MMK',
1236 'ZAR',
1237 'NAD',
1238 'AUD',
1239 'NPR',
1240 'EUR',
1241 'ANG',
1242 'XPF',
1243 'NZD',
1244 'NIO',
1245 'XOF',
1246 'NGN',
1247 'NZD',
1248 'AUD',
1249 'USD',
1250 'NOK',
1251 'OMR',
1252 'PKR',
1253 'USD',
1254 'PAB',
1255 'USD',
1256 'PGK',
1257 'PYG',
1258 'PEN',
1259 'PHP',
1260 'NZD',
1261 'PLN',
1262 'EUR',
1263 'USD',
1264 'QAR',
1265 'EUR',
1266 'ROL',
1267 'RON',
1268 'RUB',
1269 'RWF',
1270 'SHP',
1271 'XCD',
1272 'XCD',
1273 'EUR',
1274 'XCD',
1275 'WST',
1276 'EUR',
1277 'STD',
1278 'SAR',
1279 'XOF',
1280 'CSD',
1281 'EUR',
1282 'SCR',
1283 'SLL',
1284 'SGD',
1285 'SKK',
1286 'SIT',
1287 'SBD',
1288 'SOS',
1289 'ZAR',
1290 'EUR',
1291 'LKR',
1292 'SDD',
1293 'SRD',
1294 'NOK',
1295 'SZL',
1296 'SEK',
1297 'CHF',
1298 'CHW',
1299 'CHE',
1300 'SYP',
1301 'TWD',
1302 'TJS',
1303 'TZS',
1304 'THB',
1305 'USD',
1306 'XOF',
1307 'NZD',
1308 'TOP',
1309 'TTD',
1310 'TND',
1311 'TRY',
1312 'TRL',
1313 'TMM',
1314 'USD',
1315 'AUD',
1316 'UGX',
1317 'UAH',
1318 'AED',
1319 'GBP',
1320 'USD',
1321 'USS',
1322 'USN',
1323 'USD',
1324 'UYU',
1325 'UZS',
1326 'VUV',
1327 'VEB',
1328 'VND',
1329 'USD',
1330 'USD',
1331 'XPF',
1332 'MAD',
1333 'YER',
1334 'ZMK',
1335 'ZWD',
1336 'XAU',
1337 'XBA',
1338 'XBB',
1339 'XBC',
1340 'XBD',
1341 'XPD',
1342 'XPT',
1343 'XAG',
1344 'XFU',
1345 'XFO',
1346 'XTS',
1347 'XXX',
1348 );
1349 }
1350 return self::$currencyCode;
1351 }
1352
1353 /**
1354 * Get all the County from database.
1355 *
1356 * The static array county is returned, and if it's
1357 * called the first time, the <b>County DAO</b> is used
1358 * to get all the Counties.
1359 *
1360 * Note: any database errors will be trapped by the DAO.
1361 *
1362 *
1363 * @param bool|int $id - Optional id to return
1364 *
1365 * @return array
1366 * array reference of all Counties
1367 */
1368 public static function &county($id = FALSE) {
1369 if (!self::$county) {
1370
1371 $config = CRM_Core_Config::singleton();
1372 // order by id so users who populate civicrm_county can have more control over sort by the order they load the counties
1373 self::populate(self::$county, 'CRM_Core_DAO_County', TRUE, 'name', NULL, NULL, 'id');
1374 }
1375 if ($id) {
1376 if (array_key_exists($id, self::$county)) {
1377 return self::$county[$id];
1378 }
1379 else {
1380 return CRM_Core_DAO::$_nullObject;
1381 }
1382 }
1383 return self::$county;
1384 }
1385
1386 /**
1387 * @deprecated Please use the buildOptions() method in the appropriate BAO object.
1388 * Get all active payment processors
1389 *
1390 * The static array paymentProcessor is returned
1391 *
1392 *
1393 * @param bool $all
1394 * Get payment processors - default is to get only active ones.
1395 * @param bool $test
1396 * Get test payment processors.
1397 *
1398 * @param null $additionalCond
1399 *
1400 * @return array
1401 * array of all payment processors
1402 */
1403 public static function paymentProcessor($all = FALSE, $test = FALSE, $additionalCond = NULL) {
1404 $condition = "is_test = ";
1405 $condition .= ($test) ? '1' : '0';
1406
1407 if ($additionalCond) {
1408 $condition .= " AND ( $additionalCond ) ";
1409 }
1410
1411 // CRM-7178. Make sure we only include payment processors valid in this
1412 // domain
1413 $condition .= " AND domain_id = " . CRM_Core_Config::domainID();
1414
1415 $cacheKey = $condition . '_' . (int) $all;
1416 if (!isset(self::$paymentProcessor[$cacheKey])) {
1417 self::populate(self::$paymentProcessor[$cacheKey], 'CRM_Financial_DAO_PaymentProcessor', $all, 'name', 'is_active', $condition, 'is_default desc, name');
1418 }
1419
1420 return self::$paymentProcessor[$cacheKey];
1421 }
1422
1423 /**
1424 * @deprecated Please use the buildOptions() method in the appropriate BAO object.
1425 *
1426 * The static array paymentProcessorType is returned
1427 *
1428 *
1429 * @param bool $all
1430 * Get payment processors - default is to get only active ones.
1431 *
1432 * @param int $id
1433 * @param string $return
1434 *
1435 * @return array
1436 * array of all payment processor types
1437 */
1438 public static function &paymentProcessorType($all = FALSE, $id = NULL, $return = 'title') {
1439 $cacheKey = $id . '_' . $return;
1440 if (empty(self::$paymentProcessorType[$cacheKey])) {
1441 self::populate(self::$paymentProcessorType[$cacheKey], 'CRM_Financial_DAO_PaymentProcessorType', $all, $return, 'is_active', NULL, "is_default, $return", 'id');
1442 }
1443 if ($id && CRM_Utils_Array::value($id, self::$paymentProcessorType[$cacheKey])) {
1444 return self::$paymentProcessorType[$cacheKey][$id];
1445 }
1446 return self::$paymentProcessorType[$cacheKey];
1447 }
1448
1449 /**
1450 * Get all the World Regions from Database.
1451 *
1452 *
1453 * @param bool $id
1454 *
1455 * @return array
1456 * array reference of all World Regions
1457 */
1458 public static function &worldRegion($id = FALSE) {
1459 if (!self::$worldRegions) {
1460 self::populate(self::$worldRegions, 'CRM_Core_DAO_Worldregion', TRUE, 'name', NULL, NULL, 'id');
1461 }
1462
1463 if ($id) {
1464 if (array_key_exists($id, self::$worldRegions)) {
1465 return self::$worldRegions[$id];
1466 }
1467 else {
1468 return CRM_Core_DAO::$_nullObject;
1469 }
1470 }
1471
1472 return self::$worldRegions;
1473 }
1474
1475 /**
1476 * @deprecated Please use the buildOptions() method in the appropriate BAO object.
1477 *
1478 * Get all Activity Statuses.
1479 *
1480 * The static array activityStatus is returned
1481 *
1482 *
1483 * @param string $column
1484 *
1485 * @return array
1486 * array reference of all activity statuses
1487 */
1488 public static function &activityStatus($column = 'label') {
1489 if (NULL === self::$activityStatus) {
1490 self::$activityStatus = array();
1491 }
1492 if (!array_key_exists($column, self::$activityStatus)) {
1493 self::$activityStatus[$column] = array();
1494
1495 self::$activityStatus[$column] = CRM_Core_OptionGroup::values('activity_status', FALSE, FALSE, FALSE, NULL, $column);
1496 }
1497
1498 return self::$activityStatus[$column];
1499 }
1500
1501 /**
1502 * @deprecated Please use the buildOptions() method in the appropriate BAO object.
1503 *
1504 * Get all Visibility levels.
1505 *
1506 * The static array visibility is returned
1507 *
1508 *
1509 * @param string $column
1510 *
1511 * @return array
1512 * array reference of all Visibility levels.
1513 */
1514 public static function &visibility($column = 'label') {
1515 if (!isset(self::$visibility)) {
1516 self::$visibility = array();
1517 }
1518
1519 if (!isset(self::$visibility[$column])) {
1520 self::$visibility[$column] = CRM_Core_OptionGroup::values('visibility', FALSE, FALSE, FALSE, NULL, $column);
1521 }
1522
1523 return self::$visibility[$column];
1524 }
1525
1526 /**
1527 * @param int $countryID
1528 * @param string $field
1529 *
1530 * @return array
1531 */
1532 public static function &stateProvinceForCountry($countryID, $field = 'name') {
1533 static $_cache = NULL;
1534
1535 $cacheKey = "{$countryID}_{$field}";
1536 if (!$_cache) {
1537 $_cache = array();
1538 }
1539
1540 if (!empty($_cache[$cacheKey])) {
1541 return $_cache[$cacheKey];
1542 }
1543
1544 $query = "
1545 SELECT civicrm_state_province.{$field} name, civicrm_state_province.id id
1546 FROM civicrm_state_province
1547 WHERE country_id = %1
1548 ORDER BY name";
1549 $params = array(
1550 1 => array(
1551 $countryID,
1552 'Integer',
1553 ),
1554 );
1555
1556 $dao = CRM_Core_DAO::executeQuery($query, $params);
1557
1558 $result = array();
1559 while ($dao->fetch()) {
1560 $result[$dao->id] = $dao->name;
1561 }
1562
1563 // localise the stateProvince names if in an non-en_US locale
1564 $config = CRM_Core_Config::singleton();
1565 global $tsLocale;
1566 if ($tsLocale != '' and $tsLocale != 'en_US') {
1567 $i18n = CRM_Core_I18n::singleton();
1568 $i18n->localizeArray($result, array(
1569 'context' => 'province',
1570 ));
1571 $result = CRM_Utils_Array::asort($result);
1572 }
1573
1574 $_cache[$cacheKey] = $result;
1575
1576 CRM_Utils_Hook::buildStateProvinceForCountry($countryID, $result);
1577
1578 return $result;
1579 }
1580
1581 /**
1582 * @param int $stateID
1583 *
1584 * @return array
1585 */
1586 public static function &countyForState($stateID) {
1587 if (is_array($stateID)) {
1588 $states = implode(", ", $stateID);
1589 $query = "
1590 SELECT civicrm_county.name name, civicrm_county.id id, civicrm_state_province.abbreviation abbreviation
1591 FROM civicrm_county
1592 LEFT JOIN civicrm_state_province ON civicrm_county.state_province_id = civicrm_state_province.id
1593 WHERE civicrm_county.state_province_id in ( $states )
1594 ORDER BY civicrm_state_province.abbreviation, civicrm_county.name";
1595
1596 $dao = CRM_Core_DAO::executeQuery($query);
1597
1598 $result = array();
1599 while ($dao->fetch()) {
1600 $result[$dao->id] = $dao->abbreviation . ': ' . $dao->name;
1601 }
1602 }
1603 else {
1604
1605 static $_cache = NULL;
1606
1607 $cacheKey = "{$stateID}_name";
1608 if (!$_cache) {
1609 $_cache = array();
1610 }
1611
1612 if (!empty($_cache[$cacheKey])) {
1613 return $_cache[$cacheKey];
1614 }
1615
1616 $query = "
1617 SELECT civicrm_county.name name, civicrm_county.id id
1618 FROM civicrm_county
1619 WHERE state_province_id = %1
1620 ORDER BY name";
1621 $params = array(
1622 1 => array(
1623 $stateID,
1624 'Integer',
1625 ),
1626 );
1627
1628 $dao = CRM_Core_DAO::executeQuery($query, $params);
1629
1630 $result = array();
1631 while ($dao->fetch()) {
1632 $result[$dao->id] = $dao->name;
1633 }
1634 }
1635
1636 return $result;
1637 }
1638
1639 /**
1640 * Given a state ID return the country ID, this allows
1641 * us to populate forms and values for downstream code
1642 *
1643 * @param int $stateID
1644 *
1645 * @return int
1646 * the country id that the state belongs to
1647 */
1648 public static function countryIDForStateID($stateID) {
1649 if (empty($stateID)) {
1650 return CRM_Core_DAO::$_nullObject;
1651 }
1652
1653 $query = "
1654 SELECT country_id
1655 FROM civicrm_state_province
1656 WHERE id = %1
1657 ";
1658 $params = array(1 => array($stateID, 'Integer'));
1659
1660 return CRM_Core_DAO::singleValueQuery($query, $params);
1661 }
1662
1663 /**
1664 * Get all types of Greetings.
1665 *
1666 * The static array of greeting is returned
1667 *
1668 *
1669 * @param $filter
1670 * Get All Email Greetings - default is to get only active ones.
1671 *
1672 * @param string $columnName
1673 *
1674 * @return array
1675 * array reference of all greetings.
1676 */
1677 public static function greeting($filter, $columnName = 'label') {
1678 $index = $filter['greeting_type'] . '_' . $columnName;
1679
1680 // also add contactType to the array
1681 $contactType = CRM_Utils_Array::value('contact_type', $filter);
1682 if ($contactType) {
1683 $index .= '_' . $contactType;
1684 }
1685
1686 if (NULL === self::$greeting) {
1687 self::$greeting = array();
1688 }
1689
1690 if (!CRM_Utils_Array::value($index, self::$greeting)) {
1691 $filterCondition = NULL;
1692 if ($contactType) {
1693 $filterVal = 'v.filter =';
1694 switch ($contactType) {
1695 case 'Individual':
1696 $filterVal .= "1";
1697 break;
1698
1699 case 'Household':
1700 $filterVal .= "2";
1701 break;
1702
1703 case 'Organization':
1704 $filterVal .= "3";
1705 break;
1706 }
1707 $filterCondition .= "AND (v.filter = 0 OR {$filterVal}) ";
1708 }
1709
1710 self::$greeting[$index] = CRM_Core_OptionGroup::values($filter['greeting_type'], NULL, NULL, NULL, $filterCondition, $columnName);
1711 }
1712
1713 return self::$greeting[$index];
1714 }
1715
1716 /**
1717 * Construct array of default greeting values for contact type.
1718 *
1719 *
1720 * @return array
1721 * array reference of default greetings.
1722 */
1723 public static function &greetingDefaults() {
1724 if (!self::$greetingDefaults) {
1725 $defaultGreetings = array();
1726 $contactTypes = self::get('CRM_Contact_DAO_Contact', 'contact_type', array(
1727 'keyColumn' => 'id',
1728 'labelColumn' => 'name',
1729 ));
1730
1731 foreach ($contactTypes as $filter => $contactType) {
1732 $filterCondition = " AND (v.filter = 0 OR v.filter = $filter) AND v.is_default = 1 ";
1733
1734 foreach (CRM_Contact_BAO_Contact::$_greetingTypes as $greeting) {
1735 $tokenVal = CRM_Core_OptionGroup::values($greeting, NULL, NULL, NULL, $filterCondition, 'label');
1736 $defaultGreetings[$contactType][$greeting] = $tokenVal;
1737 }
1738 }
1739
1740 self::$greetingDefaults = $defaultGreetings;
1741 }
1742
1743 return self::$greetingDefaults;
1744 }
1745
1746 /**
1747 * Get all extensions.
1748 *
1749 * The static array extensions
1750 *
1751 * FIXME: This is called by civix but not by any core code. We
1752 * should provide an API call which civix can use instead.
1753 *
1754 *
1755 * @return array
1756 * array($fullyQualifiedName => $label) list of extensions
1757 */
1758 public static function &getExtensions() {
1759 if (!self::$extensions) {
1760 self::$extensions = array();
1761 $sql = '
1762 SELECT full_name, label
1763 FROM civicrm_extension
1764 WHERE is_active = 1
1765 ';
1766 $dao = CRM_Core_DAO::executeQuery($sql);
1767 while ($dao->fetch()) {
1768 self::$extensions[$dao->full_name] = $dao->label;
1769 }
1770 }
1771
1772 return self::$extensions;
1773 }
1774
1775 /**
1776 * Get all options values.
1777 *
1778 * The static array option values is returned
1779 *
1780 *
1781 * @param bool $optionGroupName
1782 * Get All Option Group values- default is to get only active ones.
1783 *
1784 * @param int $id
1785 * @param null $condition
1786 *
1787 * @return array
1788 * array reference of all Option Group Name
1789 */
1790 public static function accountOptionValues($optionGroupName, $id = NULL, $condition = NULL) {
1791 $cacheKey = $optionGroupName . '_' . $condition;
1792 if (empty(self::$accountOptionValues[$cacheKey])) {
1793 self::$accountOptionValues[$cacheKey] = CRM_Core_OptionGroup::values($optionGroupName, FALSE, FALSE, FALSE, $condition);
1794 }
1795 if ($id) {
1796 return CRM_Utils_Array::value($id, self::$accountOptionValues[$cacheKey]);
1797 }
1798
1799 return self::$accountOptionValues[$cacheKey];
1800 }
1801
1802 /**
1803 * Fetch the list of active extensions of type 'module'
1804 *
1805 * @param bool $fresh
1806 * Whether to forcibly reload extensions list from canonical store.
1807 *
1808 * @return array
1809 * array(array('prefix' => $, 'file' => $))
1810 */
1811 public static function getModuleExtensions($fresh = FALSE) {
1812 return CRM_Extension_System::singleton()->getMapper()->getActiveModuleFiles($fresh);
1813 }
1814
1815
1816 /**
1817 * Get all tax rates.
1818 *
1819 * The static array tax rates is returned
1820 *
1821 * @return array
1822 * array list of tax rates with the financial type
1823 */
1824 public static function getTaxRates() {
1825 if (!isset(Civi::$statics[__CLASS__]['taxRates'])) {
1826 Civi::$statics[__CLASS__]['taxRates'] = array();
1827 $sql = "
1828 SELECT fa.tax_rate, efa.entity_id
1829 FROM civicrm_entity_financial_account efa
1830 INNER JOIN civicrm_financial_account fa ON fa.id = efa.financial_account_id
1831 INNER JOIN civicrm_option_value cov ON cov.value = efa.account_relationship
1832 INNER JOIN civicrm_option_group cog ON cog.id = cov.option_group_id
1833 WHERE efa.entity_table = 'civicrm_financial_type'
1834 AND cov.name = 'Sales Tax Account is'
1835 AND cog.name = 'account_relationship'
1836 AND fa.is_active = 1";
1837 $dao = CRM_Core_DAO::executeQuery($sql);
1838 while ($dao->fetch()) {
1839 Civi::$statics[__CLASS__]['taxRates'][$dao->entity_id] = $dao->tax_rate;
1840 }
1841 }
1842
1843 return Civi::$statics[__CLASS__]['taxRates'];
1844 }
1845
1846 }