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