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