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