From 5fafc9b098086480e85e0989b8e9571ff5f56f07 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Mon, 3 Feb 2014 20:41:19 -0800 Subject: [PATCH] CRM-14165 - Add metadata-based quickform select --- CRM/Activity/Form/Activity.php | 5 +--- CRM/Core/DAO.php | 20 +++++++++++++ CRM/Core/Form.php | 53 ++++++++++++++++++++++++---------- CRM/Core/Form/Renderer.php | 14 +++++++++ CRM/Core/PseudoConstant.php | 14 ++------- 5 files changed, 76 insertions(+), 30 deletions(-) diff --git a/CRM/Activity/Form/Activity.php b/CRM/Activity/Form/Activity.php index 556e7016a2..f4b28b9df9 100644 --- a/CRM/Activity/Form/Activity.php +++ b/CRM/Activity/Form/Activity.php @@ -721,10 +721,7 @@ class CRM_Activity_Form_Activity extends CRM_Contact_Form_Task { CRM_Campaign_BAO_Campaign::accessCampaign() ) { $buildEngagementLevel = TRUE; - $this->add('select', 'engagement_level', - ts('Engagement Index'), - array('' => ts('- select -')) + CRM_Campaign_PseudoConstant::engagementLevel() - ); + $this->addSelect('CRM_Activity_BAO_Activity', 'engagement_level'); $this->addRule('engagement_level', ts('Please enter the engagement index as a number (integers only).'), 'positiveInteger' diff --git a/CRM/Core/DAO.php b/CRM/Core/DAO.php index 86f29ce359..33346c19a1 100644 --- a/CRM/Core/DAO.php +++ b/CRM/Core/DAO.php @@ -1841,6 +1841,26 @@ EOS; return $contexts; } + /** + * @param $fieldName + * @return bool|array + */ + function getFieldSpec($fieldName) { + $fields = $this->fields(); + $fieldKeys = $this->fieldKeys(); + + // Support "unique names" as well as sql names + $fieldKey = $fieldName; + if (empty($fields[$fieldKey])) { + $fieldKey = CRM_Utils_Array::value($fieldName, $fieldKeys); + } + // If neither worked then this field doesn't exist. Return false. + if (empty($fields[$fieldKey])) { + return FALSE; + } + return $fields[$fieldKey]; + } + /** * SQL version of api function to assign filters to the DAO based on the syntax * $field => array('IN' => array(4,6,9)) diff --git a/CRM/Core/Form.php b/CRM/Core/Form.php index 59997b62ad..8b20d5c652 100644 --- a/CRM/Core/Form.php +++ b/CRM/Core/Form.php @@ -901,25 +901,47 @@ class CRM_Core_Form extends HTML_QuickForm_Page { } } - function addSelect($name, $label, $prefix = NULL, $required = NULL, $extra = NULL, $select = '- select -') { - if ($prefix) { - $this->addElement('select', $name . '_id' . $prefix, $label, - array( - '' => $select) + CRM_Core_OptionGroup::values($name), $extra - ); - if ($required) { - $this->addRule($name . '_id' . $prefix, ts('Please select %1', array(1 => $label)), 'required'); - } + /** + * Adds a select based on field metadata + * TODO: This could be even more generic and widget type (select in this case) could also be read from metadata + * @param CRM_Core_DAO $baoName - string representing bao object + * @param $name + * @param array $props + * @param bool $required + * @throws CRM_Core_Exception + * @return HTML_QuickForm_Element + */ + function addSelect($baoName, $name, $props = array(), $required = FALSE) { + $options = $baoName::buildOptions($name, 'create'); + if ($options === FALSE) { + throw new CRM_Core_Exception('No option list for field ' . $name); } + if (!array_key_exists('placeholder', $props)) { + $props['placeholder'] = $required ? ts('- select -') : ts('- none -'); + } + if (!empty($props['placeholder']) && empty($props['multiple'])) { + $options = array('' => '') + $options; + } + // Handle custom field + if (strpos($name, 'custom_') === 0 && is_numeric($name[7])) { + list(, $id) = explode('_', $name); + $label = isset($props['label']) ? $props['label'] : CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomField', 'label', $id); + $props['data-option-group'] = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomField', 'option_group_id', $id); + } + // Core field else { - $this->addElement('select', $name . '_id', $label, - array( - '' => $select) + CRM_Core_OptionGroup::values($name), $extra - ); - if ($required) { - $this->addRule($name . '_id', ts('Please select %1', array(1 => $label)), 'required'); + $bao = new $baoName; + $meta = $bao->getFieldSpec($name); + $bao->free(); + // Todo: localize + $label = CRM_Utils_Array::value('label', $props, $meta['title']); + if (!empty($meta['pseudoconstant']['optionGroupName'])) { + $props['data-option-group'] = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', $meta['pseudoconstant']['optionGroupName'], 'id', 'name'); } } + $props['class'] = isset($props['class']) ? $props['class'] . ' ' : ''; + $props['class'] .= "crm-select2"; + return $this->add('select', $name, $label, $options, $required, $props); } /** @@ -1289,6 +1311,7 @@ class CRM_Core_Form extends HTML_QuickForm_Page { $val = str_replace(CRM_Core_DAO::VALUE_SEPARATOR, ',', trim($val, CRM_Core_DAO::VALUE_SEPARATOR)); $field->setValue($val); } + // TODO: we could fetch multiple values with array(IN => $val) but not all apis support this foreach (explode(',', $val) as $v) { $result = civicrm_api3($api['entity'], $api['action'], array('sequential' => 1, $api['key'] => $v)); if (!empty($result['values'])) { diff --git a/CRM/Core/Form/Renderer.php b/CRM/Core/Form/Renderer.php index 17276b44c3..bc15901d88 100644 --- a/CRM/Core/Form/Renderer.php +++ b/CRM/Core/Form/Renderer.php @@ -117,6 +117,10 @@ class CRM_Core_Form_Renderer extends HTML_QuickForm_Renderer_ArraySmarty { } } + if ($element->getType() == 'select' && $element->getAttribute('data-option-group')) { + $this->addOptionsEditLink($el, $element); + } + if (!empty($el['frozen'])) { if ($element->getAttribute('data-api-params') && $element->getAttribute('data-entity-value')) { $this->renderFrozenEntityRef($el, $element); @@ -205,6 +209,16 @@ class CRM_Core_Form_Renderer extends HTML_QuickForm_Renderer_ArraySmarty { $el['html'] = implode('; ', $display) . ''; } + + /** + * @param array $el + * @param HTML_QuickForm_element $field + */ + function addOptionsEditLink(&$el, $field) { + if (CRM_Core_Permission::check('administer CiviCRM')) { + $el['html'] .= '   '; + } + } } // end CRM_Core_Form_Renderer diff --git a/CRM/Core/PseudoConstant.php b/CRM/Core/PseudoConstant.php index 321a6e8552..8bbf859247 100644 --- a/CRM/Core/PseudoConstant.php +++ b/CRM/Core/PseudoConstant.php @@ -222,7 +222,7 @@ class CRM_Core_PseudoConstant { * - fresh boolean ignore cache entries and go back to DB * @param String $context: Context string * - * @return Array on success, FALSE on error. + * @return Array|bool - array on success, FALSE on error. * * @static */ @@ -276,20 +276,12 @@ class CRM_Core_PseudoConstant { // Core field: load schema $dao = new $daoName; - $fields = $dao->fields(); - $fieldKeys = $dao->fieldKeys(); + $fieldSpec = $dao->getFieldSpec($fieldName); $dao->free(); - - // Support "unique names" as well as sql names - $fieldKey = $fieldName; - if (empty($fields[$fieldKey])) { - $fieldKey = CRM_Utils_Array::value($fieldName, $fieldKeys); - } // If neither worked then this field doesn't exist. Return false. - if (empty($fields[$fieldKey])) { + if (empty($fieldSpec)) { return FALSE; } - $fieldSpec = $fields[$fieldKey]; // If the field is an enum, explode the enum definition and return the array. if (isset($fieldSpec['enumValues'])) { -- 2.25.1