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