protected $_action;
/**
- * the renderer used for this form
+ * The renderer used for this form
*
* @var object
*/
protected $_dateFields = array();
/**
- * cache the smarty template for efficiency reasons
+ * Cache the smarty template for efficiency reasons
*
* @var CRM_Core_Smarty
*/
public $controller;
/**
- * constants for attributes for various form elements
+ * Constants for attributes for various form elements
* attempt to standardize on the number of variations that we
* use of the below form elements
*
/**
* Add one or more css classes to the form
- * @param $className
+ * @param string $className
*/
public function addClass($className) {
$classes = $this->getAttribute('class');
}
/**
- * register all the standard rules that most forms potentially use
+ * Register all the standard rules that most forms potentially use
*
* @return void
* @access private
$this->preProcess();
+ CRM_Utils_Hook::preProcess(get_class($this), $this);
+
$this->assign('translatePermission', CRM_Core_Permission::check('translate CiviCRM'));
if (
}
/**
- * getter function for Name
+ * Getter function for Name
*
* @return string
* @access public
}
/**
- * getter function for State
+ * Getter function for State
*
* @return object
* @access public
}
/**
- * getter function for StateType
+ * Getter function for StateType
*
* @return int
* @access public
}
/**
- * getter function for title. Should be over-ridden by derived class
+ * Getter function for title. Should be over-ridden by derived class
*
* @return string
* @access public
}
/**
- * setter function for title.
+ * Setter function for title.
*
* @param string $title the title of the form
*
}
/**
- * getter function for link.
+ * Getter function for link.
*
* @return string
* @access public
}
/**
- * boolean function to determine if this is a one form page
+ * Boolean function to determine if this is a one form page
*
* @return boolean
* @access public
}
/**
- * getter function for Form Action
+ * Getter function for Form Action
*
* @return string
* @access public
}
/**
- * setter function for Form Action
+ * Setter function for Form Action
*
* @param string
*
}
/**
- * render form and return contents
+ * Render form and return contents
*
* @return string
* @access public
}
/**
- * getter function for renderer. If renderer is not set
+ * Getter function for renderer. If renderer is not set
* create one and initialize it
*
* @return object
}
/**
- * getter for action
+ * Getter for action
*
* @return int
* @access public
}
/**
- * setter for action
+ * Setter for action
*
* @param int $action the mode we want to set the form
*
}
/**
- * assign value to name in template
+ * Assign value to name in template
*
- * @param $var
- * @param mixed $value value of varaible
+ * @param string $var name of variable
+ * @param mixed $value value of variable
*
- * @internal param array|string $name name of variable
* @return void
* @access public
*/
}
/**
- * assign value to name in template by reference
+ * Assign value to name in template by reference
*
- * @param $var
+ * @param string $var name of variable
* @param mixed $value value of varaible
*
- * @internal param array|string $name name of variable
* @return void
* @access public
*/
}
/**
- * appends values to template variables
+ * Appends values to template variables
*
* @param array|string $tpl_var the template variable name(s)
* @param mixed $value the value to append
*
* @param string $name
*
- * @internal param string $type
* @return array
*/
function get_template_vars($name=null) {
}
/**
- * @param $name
+ * @param string $name
* @param $title
* @param $values
* @param array $attributes
}
/**
- * @param $id
+ * @param int $id
* @param $title
* @param bool $allowClear
* @param null $required
}
/**
- * @param $id
+ * @param int $id
* @param $title
* @param $values
* @param null $other
}
/**
- * simple shell that derived classes can call to add buttons to
+ * Simple shell that derived classes can call to add buttons to
* the form with a customized title for the main Submit
*
* @param string $title title of the main button
- * @param string $nextType
+ * @param string $nextType button type for the form after processing
* @param string $backType
* @param bool|string $submitOnce If true, add javascript to next button submit which prevents it from being clicked more than once
*
- * @internal param string $type button type for the form after processing
* @return void
* @access public
*/
}
/**
- * @param $name
+ * @param string $name
* @param string $from
* @param string $to
* @param string $label
if (!isset($props['field'])) {
$props['field'] = strrpos($name, '[') ? rtrim(substr($name, 1 + strrpos($name, '[')), ']') : $name;
}
- $info = civicrm_api3($props['entity'], 'getoptions', array(
- 'field' => $props['field'],
- 'options' => array('metadata' => array('fields'))
- )
- );
- $options = $info['values'];
+ // Fetch options from the api unless passed explicitly
+ if (isset($props['options'])) {
+ $options = $props['options'];
+ }
+ else {
+ $info = civicrm_api3($props['entity'], 'getoptions', array('field' => $props['field']));
+ $options = $info['values'];
+ }
if (!array_key_exists('placeholder', $props)) {
$props['placeholder'] = $required ? ts('- select -') : ts('- none -');
}
}
// Core field
else {
- foreach($info['metadata']['fields'] as $uniqueName => $fieldSpec) {
+ $info = civicrm_api3($props['entity'], 'getfields');
+ foreach($info['values'] as $uniqueName => $fieldSpec) {
if (
$uniqueName === $props['field'] ||
CRM_Utils_Array::value('name', $fieldSpec) === $props['field'] ||
$props['class'] = (isset($props['class']) ? $props['class'] . ' ' : '') . "crm-select2";
$props['data-api-entity'] = $props['entity'];
$props['data-api-field'] = $props['field'];
- CRM_Utils_Array::remove($props, 'label', 'entity', 'field', 'option_url');
+ CRM_Utils_Array::remove($props, 'label', 'entity', 'field', 'option_url', 'options');
return $this->add('select', $name, $label, $options, $required, $props);
}
* @param string $allowCoreTypes only present a UFGroup if its group_type includes a subset of $allowCoreTypes; e.g. 'Individual', 'Activity'
* @param string $allowSubTypes only present a UFGroup if its group_type is compatible with $allowSubypes
* @param array $entities
+ * @param bool $default //CRM-15427
*/
- function addProfileSelector($name, $label, $allowCoreTypes, $allowSubTypes, $entities) {
+ function addProfileSelector($name, $label, $allowCoreTypes, $allowSubTypes, $entities, $default = FALSE) {
// Output widget
// FIXME: Instead of adhoc serialization, use a single json_encode()
CRM_UF_Page_ProfileEditor::registerProfileScripts();
// Note: client treats ';;' as equivalent to \0, and ';;' works better in HTML
'data-group-type' => CRM_Core_BAO_UFGroup::encodeGroupType($allowCoreTypes, $allowSubTypes, ';;'),
'data-entities' => json_encode($entities),
+ //CRM-15427
+ 'data-default' => $default,
));
}
/**
- * @param $name
+ * @param string $name
* @param $label
* @param $attributes
* @param bool $forceTextarea
}
/**
- * @param $id
+ * @param int $id
* @param $title
* @param null $required
* @param null $extra
}
/**
- * @param $name
+ * @param string $name
* @param $label
* @param $options
* @param $attributes
}
/**
- * Function to add date
- * @param string $name name of the element
- * @param string $label label of the element
- * @param array $attributes key / value pair
+ * Add date
+ * @param string $name name of the element
+ * @param string $label label of the element
+ * @param array $attributes key / value pair
*
- // if you need time
- * $attributes = array ( 'addTime' => true,
- * 'formatType' => 'relative' or 'birth' etc check advanced date settings
- * );
- * @param boolean $required true if required
+ * // if you need time
+ * $attributes = array(
+ * 'addTime' => true,
+ * 'formatType' => 'relative' or 'birth' etc check advanced date settings
+ * );
+ * @param boolean $required true if required
*
*/
function addDate($name, $label, $required = FALSE, $attributes = NULL) {
}
/**
- * add a currency and money element to the form
+ * Add a currency and money element to the form
*/
function addMoney($name,
$label,
}
/**
- * add currency element to the form
+ * Add currency element to the form
*/
function addCurrency($name = 'currency',
$label = NULL,
}
/**
- * add autoselector field -if user has permission to view contacts
+ * Add autoselector field -if user has permission to view contacts
* If adding this to a form you also need to add to the tpl e.g
*
* {if !empty($selectable)}
* @param array $profiles ids of profiles that are on the form (to be autofilled)
* @param array $autoCompleteField
*
- * @internal param array $field metadata of field to use as selector including
* - name_field
* - id_field
* - url (for ajax lookup)
$this->assign('selectable', $autoCompleteField['id_field']);
$this->addEntityRef($autoCompleteField['id_field'], NULL, array('placeholder' => $autoCompleteField['placeholder'], 'api' => $autoCompleteField['api']));
- CRM_Core_Resources::singleton()->addScriptFile('civicrm', 'js/AlternateContactSelector.js')
+ CRM_Core_Resources::singleton()->addScriptFile('civicrm', 'js/AlternateContactSelector.js', 1, 'html-header')
->addSetting(array(
'form' => array('autocompletes' => $autoCompleteField),
'ids' => array('profile' => $profiles),
'placeholder' => empty($settings['required']) ? ts('- none -') : ts('- select -'),
);
CRM_Utils_Array::remove($props, 'label', 'required', 'control_field');
- $props['class'] = (empty($props['class']) ? '' : "{$props['class']} ") . 'crm-chain-select-target crm-select2';
+ $props['class'] = (empty($props['class']) ? '' : "{$props['class']} ") . 'crm-select2';
$props['data-select-prompt'] = $props['placeholder'];
$props['data-name'] = $elementName;
$this->_chainSelectFields[$settings['control_field']] = $elementName;
- return $this->add('select', $elementName, $settings['label'], array(), $settings['required'], $props);
+ // Passing NULL instead of an array of options
+ // CRM-15225 - normally QF will reject any selected values that are not part of the field's options, but due to a
+ // quirk in our patched version of HTML_QuickForm_select, this doesn't happen if the options are NULL
+ // which seems a bit dirty but it allows our dynamically-popuplated select element to function as expected.
+ return $this->add('select', $elementName, $settings['label'], NULL, $settings['required'], $props);
}
/**
*/
private function preProcessChainSelectFields() {
foreach ($this->_chainSelectFields as $control => $target) {
- $controlField = $this->getElement($control);
$targetField = $this->getElement($target);
- $controlType = $targetField->getAttribute('data-callback') == 'civicrm/ajax/jqCounty' ? 'stateProvince' : 'country';
-
- $css = (string) $controlField->getAttribute('class');
- $controlField->updateAttributes(array(
- 'class' => ($css ? "$css " : 'crm-select2 ') . 'crm-chain-select-control',
- 'data-target' => $target,
- ));
- $controlValue = $controlField->getValue();
+ $targetType = $targetField->getAttribute('data-callback') == 'civicrm/ajax/jqCounty' ? 'county' : 'stateProvince';
$options = array();
- if ($controlValue) {
- $options = CRM_Core_BAO_Location::getChainSelectValues($controlValue, $controlType, TRUE);
- if (!$options) {
- $targetField->setAttribute('placeholder', $targetField->getAttribute('data-none-prompt'));
+ // If the control field is on the form, setup chain-select and dynamically populate options
+ if ($this->elementExists($control)) {
+ $controlField = $this->getElement($control);
+ $controlType = $targetType == 'county' ? 'stateProvince' : 'country';
+
+ $targetField->setAttribute('class', $targetField->getAttribute('class') . ' crm-chain-select-target');
+
+ $css = (string) $controlField->getAttribute('class');
+ $controlField->updateAttributes(array(
+ 'class' => ($css ? "$css " : 'crm-select2 ') . 'crm-chain-select-control',
+ 'data-target' => $target,
+ ));
+ $controlValue = $controlField->getValue();
+ if ($controlValue) {
+ $options = CRM_Core_BAO_Location::getChainSelectValues($controlValue, $controlType, TRUE);
+ if (!$options) {
+ $targetField->setAttribute('placeholder', $targetField->getAttribute('data-none-prompt'));
+ }
+ } else {
+ $targetField->setAttribute('placeholder', $targetField->getAttribute('data-empty-prompt'));
+ $targetField->setAttribute('disabled', 'disabled');
}
}
+ // Control field not present - fall back to loading default options
else {
- $targetField->setAttribute('placeholder', $targetField->getAttribute('data-empty-prompt'));
- $targetField->setAttribute('disabled', 'disabled');
+ $options = CRM_Core_PseudoConstant::$targetType();
}
if (!$targetField->getAttribute('multiple')) {
$options = array('' => $targetField->getAttribute('placeholder')) + $options;
$targetField->removeAttribute('placeholder');
}
+ $targetField->_options = array();
$targetField->loadArray($options);
}
}
*/
private function validateChainSelectFields() {
foreach ($this->_chainSelectFields as $control => $target) {
- $controlValue = (array) $this->getElementValue($control);
- $targetField = $this->getElement($target);
- $controlType = $targetField->getAttribute('data-callback') == 'civicrm/ajax/jqCounty' ? 'stateProvince' : 'country';
- $targetValue = array_filter((array) $targetField->getValue());
- if ($targetValue || $this->getElementError($target)) {
- $options = CRM_Core_BAO_Location::getChainSelectValues($controlValue, $controlType, TRUE);
- if ($targetValue) {
- if (!array_intersect($targetValue, array_keys($options))) {
- $this->setElementError($target, $controlType == 'country' ? ts('State/Province does not match the selected Country') : ts('County does not match the selected State/Province'));
+ if ($this->elementExists($control)) {
+ $controlValue = (array)$this->getElementValue($control);
+ $targetField = $this->getElement($target);
+ $controlType = $targetField->getAttribute('data-callback') == 'civicrm/ajax/jqCounty' ? 'stateProvince' : 'country';
+ $targetValue = array_filter((array)$targetField->getValue());
+ if ($targetValue || $this->getElementError($target)) {
+ $options = CRM_Core_BAO_Location::getChainSelectValues($controlValue, $controlType, TRUE);
+ if ($targetValue) {
+ if (!array_intersect($targetValue, array_keys($options))) {
+ $this->setElementError($target, $controlType == 'country' ? ts('State/Province does not match the selected Country') : ts('County does not match the selected State/Province'));
+ }
+ } // Suppress "required" error for field if it has no options
+ elseif (!$options) {
+ $this->setElementError($target, NULL);
}
}
- // Suppress "required" error for field if it has no options
- elseif (!$options) {
- $this->setElementError($target, NULL);
- }
}
}
}