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