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