Revert "Merge pull request #1371 from drumm/CRM-12930-smarty-safe-mode"
[civicrm-core.git] / CRM / Core / PseudoConstant.php
index 3607893c0201b3929a1888851aae7d8b965eb8b8..ef8b6daca7e38bb897c0da2054afb4c779d612b1 100644 (file)
@@ -220,32 +220,72 @@ class CRM_Core_PseudoConstant {
    * - orderColumn string the column to use for sorting, defaults to 'weight' column if one exists, else defaults to labelColumn
    * - onlyActive boolean return only the action option values
    * - fresh      boolean ignore cache entries and go back to DB
+   * @param String $context: Context string
    *
    * @return Array on success, FALSE on error.
    *
    * @static
    */
-  public static function get($daoName, $fieldName, $params = array()) {
+  public static function get($daoName, $fieldName, $params = array(), $context = NULL) {
+    CRM_Core_DAO::buildOptionsContext($context);
     $flip = !empty($params['flip']);
+    // Merge params with defaults
+    $params += array(
+      'grouping' => FALSE,
+      'localize' => FALSE,
+      'onlyActive' => ($context == 'validate' || $context == 'create') ? FALSE : TRUE,
+      'fresh' => FALSE,
+    );
 
     // Custom fields are not in the schema
-    if (strpos($fieldName, 'custom') === 0) {
-      $dao = new CRM_Core_DAO_CustomField;
-      $dao->id = (int) substr($fieldName, 7);
-      $dao->find(TRUE);
-      $customField = (array) $dao;
-      $dao->free();
-      $output = array();
-      CRM_Core_BAO_CustomField::buildOption($customField, $output);
-      return $flip ? array_flip($output) : $output;
+    if (strpos($fieldName, 'custom_') === 0 && is_numeric($fieldName[7])) {
+      $customField = new CRM_Core_DAO_CustomField();
+      $customField->id = (int) substr($fieldName, 7);
+      $customField->find(TRUE);
+      $options = FALSE;
+
+      if (!empty($customField->option_group_id)) {
+        $options = CRM_Core_OptionGroup::valuesByID($customField->option_group_id,
+          $flip,
+          $params['grouping'],
+          $params['localize'],
+          // Note: for custom fields the 'name' column is NULL
+          CRM_Utils_Array::value('labelColumn', $params, 'label'),
+          $params['onlyActive'],
+          $params['fresh']
+        );
+      }
+      else {
+        if ($customField->data_type === 'StateProvince') {
+          $options = self::stateProvince();
+        }
+        elseif ($customField->data_type === 'Country') {
+          $options = $context == 'validate' ? self::countryIsoCode() : self::country();
+        }
+        elseif ($customField->data_type === 'Boolean') {
+          $options = $context == 'validate' ? array(0, 1) : array(1 => ts('Yes'), 0 => ts('No'));
+        }
+        $options = $options && $flip ? array_flip($options) : $options;
+      }
+      if ($options !== FALSE) {
+        CRM_Utils_Hook::customFieldOptions($customField->id, $options, FALSE);
+      }
+      $customField->free();
+      return $options;
     }
 
     // Core field: load schema
     $dao = new $daoName;
     $fields = $dao->fields();
     $fieldKeys = $dao->fieldKeys();
-    $fieldKey = $fieldKeys[$fieldName];
     $dao->free();
+
+    // Support "unique names" as well as sql names
+    $fieldKey = $fieldName;
+    if (empty($fields[$fieldKey])) {
+      $fieldKey = $fieldKeys[$fieldName];
+    }
+    // If neither worked then this field doesn't exist. Return false.
     if (empty($fields[$fieldKey])) {
       return FALSE;
     }
@@ -256,24 +296,23 @@ class CRM_Core_PseudoConstant {
       // use of a space after the comma is inconsistent in xml
       $enumStr = str_replace(', ', ',', $fieldSpec['enumValues']);
       $output = explode(',', $enumStr);
-      return $flip ? array_flip($output) : $output;
+      return array_combine($output, $output);
     }
 
     elseif (!empty($fieldSpec['pseudoconstant'])) {
       $pseudoconstant = $fieldSpec['pseudoconstant'];
-      // Merge params with defaults
+      // Merge params with schema defaults
       $params += array(
-        'grouping' => FALSE,
-        'localize' => FALSE,
-        'condition' => CRM_Utils_Array::value('condition', $pseudoconstant),
+        'condition' => CRM_Utils_Array::value('condition', $pseudoconstant, array()),
         'keyColumn' => CRM_Utils_Array::value('keyColumn', $pseudoconstant),
         'labelColumn' => CRM_Utils_Array::value('labelColumn', $pseudoconstant),
-        'onlyActive' => TRUE,
-        'fresh' => FALSE,
       );
 
       // Fetch option group from option_value table
       if(!empty($pseudoconstant['optionGroupName'])) {
+        if ($context == 'validate') {
+          $params['labelColumn'] = 'name';
+        }
         // Call our generic fn for retrieving from the option_value table
         return CRM_Core_OptionGroup::values(
           $pseudoconstant['optionGroupName'],
@@ -307,15 +346,22 @@ class CRM_Core_PseudoConstant {
           // Get list of fields for the option table
           $dao = new $daoName;
           $availableFields = array_keys($dao->fieldKeys());
-          if (in_array('is_active', $availableFields)) {
-            $wheres[] = 'is_active = 1';
-          }
           $dao->free();
 
           $select = "SELECT %1 AS id, %2 AS label";
           $from = "FROM %3";
           $wheres = array();
           $order = "ORDER BY %2";
+
+          // Use machine name instead of label in validate context
+          if ($context == 'validate') {
+            if (!empty($pseudoconstant['nameColumn'])) {
+              $params['labelColumn'] = $pseudoconstant['nameColumn'];
+            }
+            elseif (in_array('name', $availableFields)) {
+              $params['labelColumn'] = 'name';
+            }
+          }
           // Condition param can be passed as an sql clause string or an array of clauses
           if (!empty($params['condition'])) {
             $wheres[] = implode(' AND ', (array) $params['condition']);
@@ -362,9 +408,17 @@ class CRM_Core_PseudoConstant {
             $output[$dao->id] = $dao->label;
           }
           $dao->free();
-          if (!empty($params['localize'])) {
+          // Localize results
+          if (!empty($params['localize']) || $pseudoconstant['table'] == 'civicrm_country' || $pseudoconstant['table'] == 'civicrm_state_province') {
+            $I18nParams = array();
+            if ($pseudoconstant['table'] == 'civicrm_country') {
+              $I18nParams['context'] = 'country';
+            }
+            if ($pseudoconstant['table'] == 'civicrm_state_province') {
+              $I18nParams['context'] = 'province';
+            }
             $i18n = CRM_Core_I18n::singleton();
-            $i18n->localizeArray($output);
+            $i18n->localizeArray($output, $I18nParams);
             // Maintain sort by label
             if ($order == "ORDER BY %2") {
               CRM_Utils_Array::asort($output);
@@ -375,39 +429,77 @@ class CRM_Core_PseudoConstant {
         return $flip ? array_flip($output) : $output;
       }
     }
+
+    // Return "Yes" and "No" for boolean fields
+    elseif (CRM_Utils_Array::value('type', $fieldSpec) === CRM_Utils_Type::T_BOOLEAN) {
+      $output = $context == 'validate' ? array(0, 1) : array(1 => ts('Yes'), 0 => ts('No'));
+      return $flip ? array_flip($output) : $output;
+    }
     // If we're still here, it's an error. Return FALSE.
     return FALSE;
   }
 
   /**
-   * Fetch the label (or other value) for a field given its key
+   * Fetch the translated label for a field given its key
    *
-   * @param String $daoName
+   * @param String $baoName
    * @param String $fieldName
    * @param String|Int $key
-   * @param Array $params will be passed into self::get
    *
-   * @return string
+   * TODO: Accept multivalued input?
+   *
+   * @return bool|null|string
+   *   FALSE if the given field has no associated option list
+   *   NULL if the given key has no corresponding option
+   *   String if label is found
    */
-   function getValue($daoName, $fieldName, $key, $params = array()) {
-     $values = self::get($daoName, $fieldName, $params);
-     return CRM_Utils_Array::value($key, $values);
-   }
+  static function getLabel($baoName, $fieldName, $key) {
+    $values = $baoName::buildOptions($fieldName, 'get');
+    if ($values === FALSE) {
+      return FALSE;
+    }
+    return CRM_Utils_Array::value($key, $values);
+  }
 
   /**
-   * Fetch the key for a field option given its label/name
+   * Fetch the machine name for a field given its key
    *
-   * @param String $daoName
+   * @param String $baoName
+   * @param String $fieldName
+   * @param String|Int $key
+   *
+   * @return bool|null|string
+   *   FALSE if the given field has no associated option list
+   *   NULL if the given key has no corresponding option
+   *   String if label is found
+   */
+  static function getName($baoName, $fieldName, $key) {
+    $values = $baoName::buildOptions($fieldName, 'validate');
+    if ($values === FALSE) {
+      return FALSE;
+    }
+    return CRM_Utils_Array::value($key, $values);
+  }
+
+  /**
+   * Fetch the key for a field option given its name
+   *
+   * @param String $baoName
    * @param String $fieldName
    * @param String|Int $value
-   * @param Array $params will be passed into self::get
    *
-   * @return string
+   * @return bool|null|string|number
+   *   FALSE if the given field has no associated option list
+   *   NULL if the given key has no corresponding option
+   *   String|Number if key is found
    */
-   function getKey($daoName, $fieldName, $value, $params = array()) {
-     $values = self::get($daoName, $fieldName, $params);
-     return CRM_Utils_Array::key($value, $values);
-   }
+  static function getKey($baoName, $fieldName, $value) {
+    $values = $baoName::buildOptions($fieldName, 'validate');
+    if ($values === FALSE) {
+      return FALSE;
+    }
+    return CRM_Utils_Array::key($value, $values);
+  }
 
   /**
    * DEPRECATED generic populate method
@@ -486,9 +578,12 @@ class CRM_Core_PseudoConstant {
    *
    */
   public static function flush($name = 'cache') {
-    if (property_exists(self, $name)) {
+    if (isset(self::$$name)) {
       self::$$name = NULL;
     }
+    if ($name == 'cache') {
+      CRM_Core_OptionGroup::flushAll();
+    }
   }
 
   /**
@@ -565,7 +660,7 @@ class CRM_Core_PseudoConstant {
     }
     return self::$activityType[$index];
   }
+
   /**
    * Get all the State/Province from database.
    *