Merge pull request #15322 from alifrumin/removePrintIcon
[civicrm-core.git] / CRM / Core / PseudoConstant.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
fee14197 4 | CiviCRM version 5 |
6a488035 5 +--------------------------------------------------------------------+
6b83d5bd 6 | Copyright CiviCRM LLC (c) 2004-2019 |
6a488035
TO
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 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035
TO
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
6b83d5bd 46 * @copyright CiviCRM LLC (c) 2004-2019
6a488035
TO
47 */
48class CRM_Core_PseudoConstant {
49
887a4028 50 /**
d09edf64 51 * Static cache for pseudoconstant arrays.
887a4028 52 * @var array
887a4028
A
53 */
54 private static $cache;
55
6a488035
TO
56 /**
57 * activity type
58 * @var array
518fa0ee 59 * @deprecated Please use the buildOptions() method in the appropriate BAO object.
6a488035
TO
60 */
61 private static $activityType;
62
6a488035 63 /**
100fef9d 64 * States, provinces
6a488035 65 * @var array
6a488035
TO
66 */
67 private static $stateProvince;
68
69 /**
d09edf64 70 * Counties.
6a488035 71 * @var array
6a488035
TO
72 */
73 private static $county;
74
75 /**
100fef9d 76 * States/provinces abbreviations
6a488035 77 * @var array
6a488035 78 */
be2fb01f 79 private static $stateProvinceAbbreviation = [];
6a488035
TO
80
81 /**
d09edf64 82 * Country.
6a488035 83 * @var array
6a488035
TO
84 */
85 private static $country;
86
87 /**
d09edf64 88 * CountryIsoCode.
6a488035 89 * @var array
6a488035
TO
90 */
91 private static $countryIsoCode;
92
6a488035
TO
93 /**
94 * group
95 * @var array
518fa0ee 96 * @deprecated Please use the buildOptions() method in the appropriate BAO object.
6a488035
TO
97 */
98 private static $group;
99
6a488035 100 /**
100fef9d 101 * RelationshipType
6a488035 102 * @var array
6a488035
TO
103 */
104 private static $relationshipType;
105
106 /**
100fef9d 107 * Civicrm groups that are not smart groups
6a488035 108 * @var array
6a488035
TO
109 */
110 private static $staticGroup;
111
6a488035 112 /**
100fef9d 113 * Currency codes
6a488035 114 * @var array
6a488035
TO
115 */
116 private static $currencyCode;
117
6a488035 118 /**
100fef9d 119 * Payment processor
6a488035 120 * @var array
6a488035
TO
121 */
122 private static $paymentProcessor;
123
124 /**
100fef9d 125 * Payment processor types
6a488035 126 * @var array
6a488035
TO
127 */
128 private static $paymentProcessorType;
129
130 /**
131 * World Region
132 * @var array
6a488035
TO
133 */
134 private static $worldRegions;
135
6a488035
TO
136 /**
137 * activity status
138 * @var array
518fa0ee 139 * @deprecated Please use the buildOptions() method in the appropriate BAO object.
6a488035
TO
140 */
141 private static $activityStatus;
142
6a488035
TO
143 /**
144 * Visibility
145 * @var array
6a488035
TO
146 */
147 private static $visibility;
148
6a488035
TO
149 /**
150 * Greetings
151 * @var array
6a488035
TO
152 */
153 private static $greeting;
154
6a488035
TO
155 /**
156 * Extensions of type module
157 * @var array
6a488035
TO
158 */
159 private static $extensions;
160
f743a6eb
CW
161 /**
162 * Financial Account Type
163 * @var array
f743a6eb
CW
164 */
165 private static $accountOptionValues;
166
887a4028 167 /**
6d68a4cb
CW
168 * Low-level option getter, rarely accessed directly.
169 * NOTE: Rather than calling this function directly use CRM_*_BAO_*::buildOptions()
7eaff122 170 * @see https://docs.civicrm.org/dev/en/latest/framework/pseudoconstant/
6d68a4cb 171 *
76068c6a
TO
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 *
6a0b768e
TO
177 * @param string $daoName
178 * @param string $fieldName
179 * @param array $params
a42ef93c
CW
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
f743a6eb 185 * - condition string|array add condition(s) to the sql query - will be concatenated using 'AND'
091fe2a8
CW
186 * - keyColumn string the column to use for 'id'
187 * - labelColumn string the column to use for 'label'
6d68a4cb 188 * - orderColumn string the column to use for sorting, defaults to 'weight' column if one exists, else defaults to labelColumn
a42ef93c
CW
189 * - onlyActive boolean return only the action option values
190 * - fresh boolean ignore cache entries and go back to DB
353ffa53 191 * @param string $context : Context string
5b22d1b8 192 * @see CRM_Core_DAO::buildOptionsContext
887a4028 193 *
8d7a9d07 194 * @return array|bool
72b3a70c 195 * array on success, FALSE on error.
a42ef93c 196 *
887a4028 197 */
be2fb01f 198 public static function get($daoName, $fieldName, $params = [], $context = NULL) {
786ad6e1 199 CRM_Core_DAO::buildOptionsContext($context);
f2b53f26 200 $flip = !empty($params['flip']);
65c86f7d 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;
786ad6e1 205 // Merge params with defaults
be2fb01f 206 $params += [
786ad6e1 207 'grouping' => FALSE,
65c86f7d 208 'localize' => $localizeDefault,
c203a3d6 209 'onlyActive' => ($context == 'validate' || $context == 'get') ? FALSE : TRUE,
786ad6e1 210 'fresh' => FALSE,
33e61cb8 211 'context' => $context,
be2fb01f 212 ];
33e61cb8 213 $entity = CRM_Core_DAO_AllCoreTables::getBriefName(CRM_Core_DAO_AllCoreTables::getCanonicalClassName($daoName));
f2b53f26
CW
214
215 // Custom fields are not in the schema
786ad6e1 216 if (strpos($fieldName, 'custom_') === 0 && is_numeric($fieldName[7])) {
2921fb78 217 $customField = new CRM_Core_BAO_CustomField();
a3d8b390 218 $customField->id = (int) substr($fieldName, 7);
832d5c06 219 $options = $customField->getOptions($context);
2fea9ed9
CW
220 if ($options && $flip) {
221 $options = array_flip($options);
a3d8b390 222 }
786ad6e1 223 return $options;
f2b53f26
CW
224 }
225
226 // Core field: load schema
8d7a9d07 227 $dao = new $daoName();
5fafc9b0 228 $fieldSpec = $dao->getFieldSpec($fieldName);
4268623e 229
33e61cb8
CW
230 // Ensure we have the canonical name for this field
231 $fieldName = CRM_Utils_Array::value('name', $fieldSpec, $fieldName);
4268623e 232
33e61cb8 233 // Return false if field doesn't exist.
5fafc9b0 234 if (empty($fieldSpec)) {
ecc63dd6
A
235 return FALSE;
236 }
887a4028 237
887a4028
A
238 elseif (!empty($fieldSpec['pseudoconstant'])) {
239 $pseudoconstant = $fieldSpec['pseudoconstant'];
cc6443c4 240
241 // if callback is specified..
22e263ad 242 if (!empty($pseudoconstant['callback'])) {
466fce54 243 $fieldOptions = call_user_func(Civi\Core\Resolver::singleton()->get($pseudoconstant['callback']), $context);
ca0f1c4b
TL
244 //CRM-18223: Allow additions to field options via hook.
245 CRM_Utils_Hook::fieldOptions($entity, $fieldName, $fieldOptions, $params);
246 return $fieldOptions;
cc6443c4 247 }
248
786ad6e1 249 // Merge params with schema defaults
be2fb01f
CW
250 $params += [
251 'condition' => CRM_Utils_Array::value('condition', $pseudoconstant, []),
091fe2a8
CW
252 'keyColumn' => CRM_Utils_Array::value('keyColumn', $pseudoconstant),
253 'labelColumn' => CRM_Utils_Array::value('labelColumn', $pseudoconstant),
be2fb01f 254 ];
091fe2a8
CW
255
256 // Fetch option group from option_value table
22e263ad 257 if (!empty($pseudoconstant['optionGroupName'])) {
786ad6e1
CW
258 if ($context == 'validate') {
259 $params['labelColumn'] = 'name';
260 }
b432ddaa
CW
261 if ($context == 'match') {
262 $params['keyColumn'] = 'name';
263 }
a42ef93c 264 // Call our generic fn for retrieving from the option_value table
33e61cb8 265 $options = CRM_Core_OptionGroup::values(
887a4028 266 $pseudoconstant['optionGroupName'],
a42ef93c
CW
267 $flip,
268 $params['grouping'],
269 $params['localize'],
f743a6eb 270 $params['condition'] ? ' AND ' . implode(' AND ', (array) $params['condition']) : NULL,
091fe2a8 271 $params['labelColumn'] ? $params['labelColumn'] : 'label',
a42ef93c 272 $params['onlyActive'],
c0c9cd82 273 $params['fresh'],
fb011779
PN
274 $params['keyColumn'] ? $params['keyColumn'] : 'value',
275 !empty($params['orderColumn']) ? $params['orderColumn'] : 'weight'
887a4028 276 );
33e61cb8
CW
277 CRM_Utils_Hook::fieldOptions($entity, $fieldName, $options, $params);
278 return $options;
887a4028 279 }
091fe2a8
CW
280
281 // Fetch options from other tables
887a4028 282 if (!empty($pseudoconstant['table'])) {
a42ef93c
CW
283 // Normalize params so the serialized cache string will be consistent.
284 CRM_Utils_Array::remove($params, 'flip', 'fresh');
887a4028 285 ksort($params);
a1ef51e2 286 $cacheKey = $daoName . $fieldName . serialize($params);
887a4028 287
a1ef51e2 288 // Retrieve cached options
14b9e069 289 if (isset(\Civi::$statics[__CLASS__][$cacheKey]) && empty($params['fresh'])) {
290 $output = \Civi::$statics[__CLASS__][$cacheKey];
887a4028 291 }
a1ef51e2 292 else {
4539198e 293 $daoName = CRM_Core_DAO_AllCoreTables::getClassForTable($pseudoconstant['table']);
2158332a
CW
294 if (!class_exists($daoName)) {
295 return FALSE;
296 }
297 // Get list of fields for the option table
8d7a9d07 298 $dao = new $daoName();
7ae0389f 299 $availableFields = array_keys($dao->fieldKeys());
887a4028 300
a1ef51e2
CW
301 $select = "SELECT %1 AS id, %2 AS label";
302 $from = "FROM %3";
be2fb01f 303 $wheres = [];
a1ef51e2 304 $order = "ORDER BY %2";
786ad6e1 305
b432ddaa
CW
306 // Use machine name in certain contexts
307 if ($context == 'validate' || $context == 'match') {
308 $nameField = $context == 'validate' ? 'labelColumn' : 'keyColumn';
a38a89fc 309 if (!empty($pseudoconstant['nameColumn'])) {
b432ddaa 310 $params[$nameField] = $pseudoconstant['nameColumn'];
a38a89fc
CW
311 }
312 elseif (in_array('name', $availableFields)) {
b432ddaa 313 $params[$nameField] = 'name';
a38a89fc 314 }
786ad6e1 315 }
a8fdb24e
CW
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
6d68a4cb 322 // Condition param can be passed as an sql clause string or an array of clauses
a1ef51e2 323 if (!empty($params['condition'])) {
6d68a4cb 324 $wheres[] = implode(' AND ', (array) $params['condition']);
a1ef51e2 325 }
6d68a4cb 326 // onlyActive param will automatically filter on common flags
a1ef51e2 327 if (!empty($params['onlyActive'])) {
be2fb01f 328 foreach (['is_active' => 1, 'is_deleted' => 0, 'is_test' => 0, 'is_hidden' => 0] as $flag => $val) {
6d68a4cb
CW
329 if (in_array($flag, $availableFields)) {
330 $wheres[] = "$flag = $val";
331 }
a1ef51e2
CW
332 }
333 }
6d68a4cb
CW
334 // Filter domain specific options
335 if (in_array('domain_id', $availableFields)) {
336 $wheres[] = 'domain_id = ' . CRM_Core_Config::domainID();
337 }
be2fb01f
CW
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 ];
a1ef51e2
CW
343 // Add orderColumn param
344 if (!empty($params['orderColumn'])) {
be2fb01f 345 $queryParams[4] = [$params['orderColumn'], 'String', CRM_Core_DAO::QUERY_FORMAT_NO_QUOTES];
a1ef51e2
CW
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 }
a42ef93c 356
be2fb01f 357 $output = [];
a1ef51e2
CW
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 }
a3d8b390
CW
367 // Localize results
368 if (!empty($params['localize']) || $pseudoconstant['table'] == 'civicrm_country' || $pseudoconstant['table'] == 'civicrm_state_province') {
be2fb01f 369 $I18nParams = [];
65c86f7d 370 if (isset($fieldSpec['localize_context'])) {
371 $I18nParams['context'] = $fieldSpec['localize_context'];
a3d8b390 372 }
a1ef51e2 373 $i18n = CRM_Core_I18n::singleton();
a3d8b390 374 $i18n->localizeArray($output, $I18nParams);
a1ef51e2
CW
375 // Maintain sort by label
376 if ($order == "ORDER BY %2") {
377 CRM_Utils_Array::asort($output);
378 }
379 }
33e61cb8 380 CRM_Utils_Hook::fieldOptions($entity, $fieldName, $output, $params);
14b9e069 381 \Civi::$statics[__CLASS__][$cacheKey] = $output;
a1ef51e2
CW
382 }
383 return $flip ? array_flip($output) : $output;
887a4028
A
384 }
385 }
a3d8b390
CW
386
387 // Return "Yes" and "No" for boolean fields
388 elseif (CRM_Utils_Array::value('type', $fieldSpec) === CRM_Utils_Type::T_BOOLEAN) {
be2fb01f 389 $output = $context == 'validate' ? [0, 1] : CRM_Core_SelectValues::boolean();
33e61cb8 390 CRM_Utils_Hook::fieldOptions($entity, $fieldName, $output, $params);
a3d8b390
CW
391 return $flip ? array_flip($output) : $output;
392 }
887a4028
A
393 // If we're still here, it's an error. Return FALSE.
394 return FALSE;
395 }
396
6a488035 397 /**
d09edf64 398 * Fetch the translated label for a field given its key.
dcda1cd5 399 *
6a0b768e
TO
400 * @param string $baoName
401 * @param string $fieldName
e97c66ff 402 * @param string|int $key
a8c23526
CW
403 *
404 * TODO: Accept multivalued input?
dcda1cd5 405 *
2a3f958d
CW
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
dcda1cd5 410 */
00be9182 411 public static function getLabel($baoName, $fieldName, $key) {
a8c23526
CW
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 /**
d09edf64 420 * Fetch the machine name for a field given its key.
a8c23526 421 *
6a0b768e
TO
422 * @param string $baoName
423 * @param string $fieldName
e97c66ff 424 * @param string|int $key
a8c23526
CW
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 */
00be9182 431 public static function getName($baoName, $fieldName, $key) {
a8c23526 432 $values = $baoName::buildOptions($fieldName, 'validate');
2a3f958d
CW
433 if ($values === FALSE) {
434 return FALSE;
435 }
436 return CRM_Utils_Array::value($key, $values);
437 }
dcda1cd5
CW
438
439 /**
d09edf64 440 * Fetch the key for a field option given its name.
dcda1cd5 441 *
6a0b768e
TO
442 * @param string $baoName
443 * @param string $fieldName
e97c66ff 444 * @param string|int $value
dcda1cd5 445 *
8d7a9d07 446 * @return bool|null|string|int
2a3f958d
CW
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
dcda1cd5 450 */
00be9182 451 public static function getKey($baoName, $fieldName, $value) {
a8c23526 452 $values = $baoName::buildOptions($fieldName, 'validate');
2a3f958d
CW
453 if ($values === FALSE) {
454 return FALSE;
455 }
456 return CRM_Utils_Array::key($value, $values);
457 }
dcda1cd5 458
e869b07d
CW
459 /**
460 * Lookup the admin page at which a field's option list can be edited
461 * @param $fieldSpec
462 * @return string|null
463 */
00be9182 464 public static function getOptionEditUrl($fieldSpec) {
e869b07d
CW
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
e1462487 476 list(, $parent, , $child) = explode('_', $daoName);
e869b07d 477 $sql = "SELECT path FROM civicrm_menu
e1462487
CW
478 WHERE page_callback LIKE '%CRM_Admin_Page_$child%' OR page_callback LIKE '%CRM_{$parent}_Page_$child%'
479 ORDER BY page_callback
e869b07d 480 LIMIT 1";
46710ea6 481 return CRM_Core_DAO::singleValueQuery($sql);
e869b07d
CW
482 }
483 return NULL;
484 }
485
dcda1cd5 486 /**
887688b9 487 * @deprecated generic populate method.
c490a46a 488 * All pseudoconstant functions that use this method are also @deprecated
6a488035
TO
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 *
6a0b768e
TO
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.
745b795a 507 *
8eedd10a 508 * @param bool $orderby
745b795a 509 * @param string $key
8eedd10a 510 * @param bool $force
6a488035 511 *
8eedd10a 512 * @return array
6a488035 513 */
8360b701
DL
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 ) {
77f080cb 525 $cacheKey = CRM_Utils_Cache::cleanKey("CRM_PC_{$name}_{$all}_{$key}_{$retrieve}_{$filter}_{$condition}_{$orderby}");
353ffa53
TO
526 $cache = CRM_Utils_Cache::singleton();
527 $var = $cache->get($cacheKey);
4f468a50 528 if ($var !== NULL && empty($force)) {
6a488035
TO
529 return $var;
530 }
531
5836c35a 532 /* @var CRM_Core_DAO $object */
8d7a9d07 533 $object = new $name();
6a488035
TO
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;
5836c35a
CW
550 $aclClauses = array_filter($name::getSelectWhereClause());
551 foreach ($aclClauses as $clause) {
552 $object->whereAdd($clause);
553 }
6a488035
TO
554 }
555
556 $object->find();
be2fb01f 557 $var = [];
6a488035
TO
558 while ($object->fetch()) {
559 $var[$object->$key] = $object->$retrieve;
560 }
561
562 $cache->set($cacheKey, $var);
563 }
564
565 /**
d09edf64 566 * Flush given pseudoconstant so it can be reread from db.
6a488035
TO
567 * nex time it's requested.
568 *
2a6da8d7 569 * @param bool|string $name pseudoconstant to be flushed
6a488035 570 */
2683ce94 571 public static function flush($name = 'cache') {
80085473 572 if (isset(self::$$name)) {
fa56270d
CW
573 self::$$name = NULL;
574 }
80085473
CW
575 if ($name == 'cache') {
576 CRM_Core_OptionGroup::flushAll();
7c990617 577 if (isset(\Civi::$statics[__CLASS__])) {
578 unset(\Civi::$statics[__CLASS__]);
579 }
80085473 580 }
6a488035
TO
581 }
582
6a488035 583 /**
c490a46a 584 * @deprecated Please use the buildOptions() method in the appropriate BAO object.
a19392e7 585 *
6a488035
TO
586 * Get all Activty types.
587 *
588 * The static array activityType is returned
589 *
6a488035 590 *
a6c01b45
CW
591 * @return array
592 * array reference of all activity types.
6a488035
TO
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) {
be2fb01f 607 self::$activityType = [];
6a488035
TO
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
be2fb01f 620 $componentIds = [];
6a488035
TO
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 }
bdd7b275 648 $condition = $condition . ' AND ' . $componentClause;
6a488035
TO
649
650 self::$activityType[$index] = CRM_Core_OptionGroup::values('activity_type', FALSE, FALSE, FALSE, $condition, $returnColumn);
651 }
652 return self::$activityType[$index];
653 }
0e6e8724 654
6a488035
TO
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 *
6a488035 664 *
6a0b768e 665 * @param bool|int $id - Optional id to return
6a488035 666 *
2a6da8d7 667 * @param bool $limit
6a488035 668 *
a6c01b45
CW
669 * @return array
670 * array reference of all State/Provinces.
6a488035
TO
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;
6a488035
TO
675 if ($limit) {
676 $countryIsoCodes = self::countryIsoCode();
0acb7f15 677 $limitCodes = CRM_Core_BAO_Country::provinceLimit();
be2fb01f 678 $limitIds = [];
6a488035
TO
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
98466ff9 692 $tsLocale = CRM_Core_I18n::getLocale();
6a488035
TO
693 if ($tsLocale != '' and $tsLocale != 'en_US') {
694 $i18n = CRM_Core_I18n::singleton();
be2fb01f 695 $i18n->localizeArray(self::$stateProvince, [
353ffa53 696 'context' => 'province',
be2fb01f 697 ]);
6a488035
TO
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 *
6a488035 718 *
6a0b768e 719 * @param bool|int $id - Optional id to return
2a6da8d7
EM
720 *
721 * @param bool $limit
6a488035 722 *
a6c01b45
CW
723 * @return array
724 * array reference of all State/Province abbreviations.
6a488035 725 */
a8215a8d 726 public static function stateProvinceAbbreviation($id = FALSE, $limit = TRUE) {
05a8d245 727 if ($id && is_numeric($id)) {
728 if (!array_key_exists($id, (array) self::$stateProvinceAbbreviation)) {
729 $query = "SELECT abbreviation
6a488035
TO
730FROM civicrm_state_province
731WHERE id = %1";
be2fb01f
CW
732 $params = [
733 1 => [
05a8d245 734 $id,
735 'Integer',
be2fb01f
CW
736 ],
737 ];
05a8d245 738 self::$stateProvinceAbbreviation[$id] = CRM_Core_DAO::singleValueQuery($query, $params);
739 }
740 return self::$stateProvinceAbbreviation[$id];
6a488035 741 }
05a8d245 742 else {
6a488035
TO
743 $whereClause = FALSE;
744
745 if ($limit) {
6a488035 746 $countryIsoCodes = self::countryIsoCode();
0acb7f15 747 $limitCodes = CRM_Core_BAO_Country::provinceLimit();
be2fb01f 748 $limitIds = [];
6a488035
TO
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
6a488035
TO
763 return self::$stateProvinceAbbreviation;
764 }
765
4352bd72 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])) {
be2fb01f 776 \Civi::$statics[__CLASS__]['stateProvinceAbbreviationForCountry'][$countryID] = [];
4352bd72 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
6a488035
TO
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 *
6a488035 801 *
dd244018 802 * @param bool|int $id - Optional id to return
6a488035 803 *
dd244018 804 * @param bool $applyLimit
6a488035 805 *
1273d77c 806 * @return array|null
a6c01b45 807 * array reference of all countries.
6a488035
TO
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();
be2fb01f 813 $limitCodes = [];
6a488035
TO
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
0acb7f15 819 $limitCodes = CRM_Core_BAO_Country::countryLimit();
6a488035 820 if (!is_array($limitCodes)) {
be2fb01f 821 $limitCodes = [
6a488035 822 $config->countryLimit => 1,
be2fb01f 823 ];
6a488035
TO
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
d14f0a66 839 if (CRM_Core_BAO_Country::defaultContactCountry()) {
6a488035 840 $countryIsoCodes = self::countryIsoCode();
d14f0a66 841 $defaultID = array_search(CRM_Core_BAO_Country::defaultContactCountry(), $countryIsoCodes);
6a488035
TO
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
98466ff9 849 $tsLocale = CRM_Core_I18n::getLocale();
6a488035
TO
850 if ($tsLocale != '' and $tsLocale != 'en_US') {
851 $i18n = CRM_Core_I18n::singleton();
be2fb01f 852 $i18n->localizeArray(self::$country, [
353ffa53 853 'context' => 'country',
be2fb01f 854 ]);
6a488035
TO
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 {
1273d77c 863 return NULL;
6a488035
TO
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 *
6a488035 878 *
fd31fa4c 879 * @param bool $id
6a488035 880 *
a6c01b45
CW
881 * @return array
882 * array reference of all country ISO codes.
6a488035
TO
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 {
7cdc9e9f 893 return CRM_Core_DAO::$_nullObject;
6a488035
TO
894 }
895 }
896 return self::$countryIsoCode;
897 }
898
6a488035 899 /**
c490a46a 900 * @deprecated Please use the buildOptions() method in the appropriate BAO object.
29494eef 901 *
6a488035
TO
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 *
6a0b768e
TO
910 * @param string $groupType
911 * Type of group(Access/Mailing).
912 * @param bool $excludeHidden
913 * Exclude hidden groups.
6a488035 914 *
6a488035 915 *
a6c01b45
CW
916 * @return array
917 * array reference of all groups.
6a488035 918 */
addbec40 919 public static function allGroup($groupType = NULL, $excludeHidden = TRUE) {
1678a63b 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 }
6a488035 925 $condition = CRM_Contact_BAO_Group::groupTypeCondition($groupType, $excludeHidden);
addbec40 926 $groupKey = ($groupType ? $groupType : 'null') . !empty($excludeHidden);
6a488035 927
6d054a8e 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);
6a488035 930 }
6d054a8e 931 return Civi::$statics[__CLASS__]['groups']['allGroup'][$groupKey];
6a488035
TO
932 }
933
6a488035 934 /**
d09edf64 935 * Get all permissioned groups from database.
6a488035
TO
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 *
6a0b768e
TO
943 * @param string $groupType
944 * Type of group(Access/Mailing).
945 * @param bool $excludeHidden
946 * Exclude hidden groups.
dd244018 947 *
6a488035 948 *
a6c01b45
CW
949 * @return array
950 * array reference of all groups.
6a488035
TO
951 */
952 public static function group($groupType = NULL, $excludeHidden = TRUE) {
953 return CRM_Core_Permission::group($groupType, $excludeHidden);
954 }
955
24431f7b 956 /**
d09edf64 957 * Fetch groups in a nested format suitable for use in select form element.
24431f7b
CW
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
6a488035 968 /**
d09edf64 969 * Get all permissioned groups from database.
6a488035
TO
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 *
6a488035 977 *
dd244018
EM
978 * @param bool $onlyPublic
979 * @param null $groupType
980 * @param bool $excludeHidden
6a488035 981 *
a6c01b45
CW
982 * @return array
983 * array reference of all groups.
6a488035
TO
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
6a488035
TO
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 *
6a0b768e
TO
1015 * @param string $valueColumnName
1016 * Db column name/label.
1017 * @param bool $reset
1018 * Reset relationship types if true.
bf48aa29 1019 * @param bool $isActive
fa8e67b8 1020 * Filter by is_active. NULL to disable.
6a488035 1021 *
a6c01b45
CW
1022 * @return array
1023 * array reference of all relationship types.
6a488035 1024 */
fa8e67b8
TO
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) {
be2fb01f 1028 self::$relationshipType[$cacheKey] = [];
6a488035
TO
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");
fa8e67b8
TO
1037 if ($isActive !== NULL) {
1038 $relationshipTypeDAO->is_active = $isActive;
1039 }
6a488035
TO
1040 $relationshipTypeDAO->find();
1041 while ($relationshipTypeDAO->fetch()) {
1042
be2fb01f 1043 self::$relationshipType[$cacheKey][$relationshipTypeDAO->id] = [
05802b8e 1044 'id' => $relationshipTypeDAO->id,
6a488035
TO
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",
be2fb01f 1051 ];
6a488035
TO
1052 }
1053 }
1054
fa8e67b8 1055 return self::$relationshipType[$cacheKey];
6a488035
TO
1056 }
1057
6a488035 1058 /**
100fef9d 1059 * Get all the ISO 4217 currency codes
6a488035
TO
1060 *
1061 * so far, we use this for validation only, so there's no point of putting this into the database
1062 *
6a488035 1063 *
a6c01b45
CW
1064 * @return array
1065 * array reference of all currency codes
6a488035
TO
1066 */
1067 public static function &currencyCode() {
1068 if (!self::$currencyCode) {
3b5223ee
HF
1069
1070 $query = "SELECT name FROM civicrm_currency";
1071 $dao = CRM_Core_DAO::executeQuery($query);
be2fb01f 1072 $currencyCode = [];
3b5223ee
HF
1073 while ($dao->fetch()) {
1074 self::$currencyCode[] = $dao->name;
1075 }
6a488035
TO
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 *
6a488035 1089 *
6a0b768e 1090 * @param bool|int $id - Optional id to return
6a488035 1091 *
a6c01b45
CW
1092 * @return array
1093 * array reference of all Counties
6a488035
TO
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 {
7cdc9e9f 1107 return CRM_Core_DAO::$_nullObject;
6a488035
TO
1108 }
1109 }
1110 return self::$county;
1111 }
1112
6a488035 1113 /**
c490a46a 1114 * @deprecated Please use the buildOptions() method in the appropriate BAO object.
6a488035
TO
1115 * Get all active payment processors
1116 *
1117 * The static array paymentProcessor is returned
1118 *
6a488035 1119 *
6a0b768e
TO
1120 * @param bool $all
1121 * Get payment processors - default is to get only active ones.
1122 * @param bool $test
1123 * Get test payment processors.
6a488035 1124 *
77b97be7 1125 * @param null $additionalCond
6a488035 1126 *
a6c01b45
CW
1127 * @return array
1128 * array of all payment processors
6a488035 1129 */
d6944518 1130 public static function paymentProcessor($all = FALSE, $test = FALSE, $additionalCond = NULL) {
6a488035
TO
1131 $condition = "is_test = ";
1132 $condition .= ($test) ? '1' : '0';
1133
1134 if ($additionalCond) {
1135 $condition .= " AND ( $additionalCond ) ";
1136 }
1137
b44e3f84 1138 // CRM-7178. Make sure we only include payment processors valid in this
6a488035
TO
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 /**
c490a46a 1151 * @deprecated Please use the buildOptions() method in the appropriate BAO object.
6a488035
TO
1152 *
1153 * The static array paymentProcessorType is returned
1154 *
6a488035 1155 *
6a0b768e
TO
1156 * @param bool $all
1157 * Get payment processors - default is to get only active ones.
6a488035 1158 *
100fef9d 1159 * @param int $id
77b97be7 1160 * @param string $return
6a488035 1161 *
a6c01b45
CW
1162 * @return array
1163 * array of all payment processor types
6a488035
TO
1164 */
1165 public static function &paymentProcessorType($all = FALSE, $id = NULL, $return = 'title') {
86bfa4f6 1166 $cacheKey = $id . '_' . $return;
6a488035
TO
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 /**
d09edf64 1177 * Get all the World Regions from Database.
6a488035 1178 *
6a488035 1179 *
77b97be7
EM
1180 * @param bool $id
1181 *
a6c01b45
CW
1182 * @return array
1183 * array reference of all World Regions
6a488035
TO
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 {
7cdc9e9f 1195 return CRM_Core_DAO::$_nullObject;
6a488035
TO
1196 }
1197 }
1198
1199 return self::$worldRegions;
1200 }
1201
6a488035 1202 /**
c490a46a 1203 * @deprecated Please use the buildOptions() method in the appropriate BAO object.
29494eef 1204 *
6a488035
TO
1205 * Get all Activity Statuses.
1206 *
1207 * The static array activityStatus is returned
1208 *
6a488035 1209 *
77b97be7
EM
1210 * @param string $column
1211 *
a6c01b45
CW
1212 * @return array
1213 * array reference of all activity statuses
6a488035
TO
1214 */
1215 public static function &activityStatus($column = 'label') {
1216 if (NULL === self::$activityStatus) {
be2fb01f 1217 self::$activityStatus = [];
6a488035
TO
1218 }
1219 if (!array_key_exists($column, self::$activityStatus)) {
be2fb01f 1220 self::$activityStatus[$column] = [];
6a488035
TO
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
6a488035 1228 /**
c490a46a 1229 * @deprecated Please use the buildOptions() method in the appropriate BAO object.
a19392e7 1230 *
6a488035
TO
1231 * Get all Visibility levels.
1232 *
1233 * The static array visibility is returned
1234 *
6a488035 1235 *
77b97be7 1236 * @param string $column
6a488035 1237 *
a6c01b45
CW
1238 * @return array
1239 * array reference of all Visibility levels.
6a488035
TO
1240 */
1241 public static function &visibility($column = 'label') {
1242 if (!isset(self::$visibility)) {
be2fb01f 1243 self::$visibility = [];
6a488035
TO
1244 }
1245
1246 if (!isset(self::$visibility[$column])) {
1247 self::$visibility[$column] = CRM_Core_OptionGroup::values('visibility', FALSE, FALSE, FALSE, NULL, $column);
2aa397bc 1248 }
6a488035
TO
1249
1250 return self::$visibility[$column];
1251 }
1252
a0ee3941 1253 /**
100fef9d 1254 * @param int $countryID
a0ee3941
EM
1255 * @param string $field
1256 *
1257 * @return array
1258 */
6a488035
TO
1259 public static function &stateProvinceForCountry($countryID, $field = 'name') {
1260 static $_cache = NULL;
1261
1262 $cacheKey = "{$countryID}_{$field}";
1263 if (!$_cache) {
be2fb01f 1264 $_cache = [];
6a488035
TO
1265 }
1266
1267 if (!empty($_cache[$cacheKey])) {
1268 return $_cache[$cacheKey];
1269 }
1270
1271 $query = "
1272SELECT civicrm_state_province.{$field} name, civicrm_state_province.id id
1273 FROM civicrm_state_province
1274WHERE country_id = %1
1275ORDER BY name";
be2fb01f
CW
1276 $params = [
1277 1 => [
6a488035
TO
1278 $countryID,
1279 'Integer',
be2fb01f
CW
1280 ],
1281 ];
6a488035
TO
1282
1283 $dao = CRM_Core_DAO::executeQuery($query, $params);
1284
be2fb01f 1285 $result = [];
6a488035
TO
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();
98466ff9 1292 $tsLocale = CRM_Core_I18n::getLocale();
6a488035
TO
1293 if ($tsLocale != '' and $tsLocale != 'en_US') {
1294 $i18n = CRM_Core_I18n::singleton();
be2fb01f 1295 $i18n->localizeArray($result, [
6a488035 1296 'context' => 'province',
be2fb01f 1297 ]);
6a488035
TO
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
a0ee3941 1308 /**
100fef9d 1309 * @param int $stateID
a0ee3941
EM
1310 *
1311 * @return array
1312 */
6a488035
TO
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
be2fb01f 1325 $result = [];
6a488035
TO
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) {
be2fb01f 1336 $_cache = [];
6a488035
TO
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";
be2fb01f
CW
1348 $params = [
1349 1 => [
6a488035
TO
1350 $stateID,
1351 'Integer',
be2fb01f
CW
1352 ],
1353 ];
6a488035
TO
1354
1355 $dao = CRM_Core_DAO::executeQuery($query, $params);
1356
be2fb01f 1357 $result = [];
6a488035
TO
1358 while ($dao->fetch()) {
1359 $result[$dao->id] = $dao->name;
1360 }
1361 }
1362
1363 return $result;
1364 }
1365
b05e28de
DL
1366 /**
1367 * Given a state ID return the country ID, this allows
1368 * us to populate forms and values for downstream code
1369 *
5a4f6742 1370 * @param int $stateID
b05e28de 1371 *
1273d77c 1372 * @return int|null
a6c01b45 1373 * the country id that the state belongs to
b05e28de 1374 */
00be9182 1375 public static function countryIDForStateID($stateID) {
b05e28de 1376 if (empty($stateID)) {
1273d77c 1377 return NULL;
b05e28de
DL
1378 }
1379
1380 $query = "
1381SELECT country_id
1382FROM civicrm_state_province
1383WHERE id = %1
1384";
be2fb01f 1385 $params = [1 => [$stateID, 'Integer']];
b05e28de
DL
1386
1387 return CRM_Core_DAO::singleValueQuery($query, $params);
1388 }
1389
6a488035
TO
1390 /**
1391 * Get all types of Greetings.
1392 *
1393 * The static array of greeting is returned
1394 *
6a488035 1395 *
6a0b768e
TO
1396 * @param $filter
1397 * Get All Email Greetings - default is to get only active ones.
6a488035 1398 *
77b97be7 1399 * @param string $columnName
6a488035 1400 *
a6c01b45
CW
1401 * @return array
1402 * array reference of all greetings.
6a488035
TO
1403 */
1404 public static function greeting($filter, $columnName = 'label') {
5f35a2d9 1405 if (!isset(Civi::$statics[__CLASS__]['greeting'])) {
be2fb01f 1406 Civi::$statics[__CLASS__]['greeting'] = [];
5f35a2d9 1407 }
1408
6a488035
TO
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
5f35a2d9 1417 if (!CRM_Utils_Array::value($index, Civi::$statics[__CLASS__]['greeting'])) {
6a488035
TO
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
5f35a2d9 1437 Civi::$statics[__CLASS__]['greeting'][$index] = CRM_Core_OptionGroup::values($filter['greeting_type'], NULL, NULL, NULL, $filterCondition, $columnName);
6a488035
TO
1438 }
1439
5f35a2d9 1440 return Civi::$statics[__CLASS__]['greeting'][$index];
6a488035
TO
1441 }
1442
6a488035 1443 /**
d09edf64 1444 * Get all extensions.
6a488035
TO
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 *
6a488035 1451 *
a6c01b45
CW
1452 * @return array
1453 * array($fullyQualifiedName => $label) list of extensions
6a488035
TO
1454 */
1455 public static function &getExtensions() {
1456 if (!self::$extensions) {
6542d699 1457 $compat = CRM_Extension_System::getCompatibilityInfo();
be2fb01f 1458 self::$extensions = [];
6a488035
TO
1459 $sql = '
1460 SELECT full_name, label
1461 FROM civicrm_extension
1462 WHERE is_active = 1
1463 ';
1464 $dao = CRM_Core_DAO::executeQuery($sql);
1465 while ($dao->fetch()) {
6542d699
TO
1466 if (!empty($compat[$dao->full_name]['force-uninstall'])) {
1467 continue;
1468 }
6a488035
TO
1469 self::$extensions[$dao->full_name] = $dao->label;
1470 }
1471 }
1472
1473 return self::$extensions;
1474 }
1475
f743a6eb 1476 /**
d09edf64 1477 * Get all options values.
f743a6eb
CW
1478 *
1479 * The static array option values is returned
1480 *
f743a6eb 1481 *
6a0b768e
TO
1482 * @param bool $optionGroupName
1483 * Get All Option Group values- default is to get only active ones.
f743a6eb 1484 *
100fef9d 1485 * @param int $id
77b97be7 1486 * @param null $condition
f743a6eb 1487 *
a6c01b45
CW
1488 * @return array
1489 * array reference of all Option Group Name
f743a6eb 1490 */
2aa397bc 1491 public static function accountOptionValues($optionGroupName, $id = NULL, $condition = NULL) {
f743a6eb
CW
1492 $cacheKey = $optionGroupName . '_' . $condition;
1493 if (empty(self::$accountOptionValues[$cacheKey])) {
2aa397bc 1494 self::$accountOptionValues[$cacheKey] = CRM_Core_OptionGroup::values($optionGroupName, FALSE, FALSE, FALSE, $condition);
f743a6eb
CW
1495 }
1496 if ($id) {
1497 return CRM_Utils_Array::value($id, self::$accountOptionValues[$cacheKey]);
1498 }
1499
1500 return self::$accountOptionValues[$cacheKey];
1501 }
1502
6a488035
TO
1503 /**
1504 * Fetch the list of active extensions of type 'module'
1505 *
5a4f6742
CW
1506 * @param bool $fresh
1507 * Whether to forcibly reload extensions list from canonical store.
6a488035 1508 *
a6c01b45
CW
1509 * @return array
1510 * array(array('prefix' => $, 'file' => $))
6a488035
TO
1511 */
1512 public static function getModuleExtensions($fresh = FALSE) {
1513 return CRM_Extension_System::singleton()->getMapper()->getActiveModuleFiles($fresh);
1514 }
dc428161 1515
dc428161 1516 /**
d09edf64 1517 * Get all tax rates.
dc428161 1518 *
1519 * The static array tax rates is returned
1520 *
a6c01b45
CW
1521 * @return array
1522 * array list of tax rates with the financial type
dc428161 1523 */
1524 public static function getTaxRates() {
27864d8a 1525 if (!isset(Civi::$statics[__CLASS__]['taxRates'])) {
be2fb01f
CW
1526 Civi::$statics[__CLASS__]['taxRates'] = [];
1527 $option = civicrm_api3('option_value', 'get', [
a38ebe6a
SL
1528 'sequential' => 1,
1529 'option_group_id' => 'account_relationship',
1530 'name' => 'Sales Tax Account is',
be2fb01f
CW
1531 ]);
1532 $value = [];
a38ebe6a 1533 if ($option['count'] !== 0) {
02b2d071
SL
1534 if ($option['count'] > 1) {
1535 foreach ($option['values'] as $opt) {
1536 $value[] = $opt['value'];
1537 }
1538 }
1539 else {
1540 $value[] = $option['values'][0]['value'];
1541 }
518fa0ee 1542 $where = 'AND efa.account_relationship IN (' . implode(', ', $value) . ' )';
a38ebe6a
SL
1543 }
1544 else {
1545 $where = '';
1546 }
dc428161 1547 $sql = "
1548 SELECT fa.tax_rate, efa.entity_id
1549 FROM civicrm_entity_financial_account efa
1550 INNER JOIN civicrm_financial_account fa ON fa.id = efa.financial_account_id
dc428161 1551 WHERE efa.entity_table = 'civicrm_financial_type'
a38ebe6a 1552 {$where}
dc428161 1553 AND fa.is_active = 1";
1554 $dao = CRM_Core_DAO::executeQuery($sql);
1555 while ($dao->fetch()) {
27864d8a 1556 Civi::$statics[__CLASS__]['taxRates'][$dao->entity_id] = $dao->tax_rate;
dc428161 1557 }
1558 }
1559
27864d8a 1560 return Civi::$statics[__CLASS__]['taxRates'];
dc428161 1561 }
96025800 1562
f61d1b83
AS
1563 /**
1564 * Get participant status class options.
1565 *
1566 * @return array
1567 */
1568 public static function emailOnHoldOptions() {
be2fb01f 1569 return [
f61d1b83
AS
1570 '0' => ts('No'),
1571 '1' => ts('On Hold Bounce'),
1572 '2' => ts('On Hold Opt Out'),
be2fb01f 1573 ];
f61d1b83
AS
1574 }
1575
6a488035 1576}