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