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