'two',
4 => 'four',
6 => 'six',
8 => 'eight',
12 => 'twelve',
20 => 'medium',
30 => 'big',
45 => 'huge',
);
/**
* Constructor.
*/
public function __construct() {
$template = CRM_Core_Smarty::singleton();
parent::__construct($template);
}
/**
* Static instance provider.
*
* Method providing static instance of as in Singleton pattern.
*/
public static function &singleton() {
if (!isset(self::$_singleton)) {
self::$_singleton = new CRM_Core_Form_Renderer();
}
return self::$_singleton;
}
/**
* Creates an array representing an element containing.
* the key for storing this. We allow the parent to do most of the
* work, but then we add some CiviCRM specific enhancements to
* make the html compliant with our css etc
*
*
* @param HTML_QuickForm_element $element
* @param bool $required
* Whether an element is required.
* @param string $error
* Error associated with the element.
*
* @return array
*/
public function _elementToArray(&$element, $required, $error) {
self::updateAttributes($element, $required, $error);
$el = parent::_elementToArray($element, $required, $error);
// add label html
if (!empty($el['label'])) {
$id = $element->getAttribute('id');
if (!empty($id)) {
$el['label'] = '';
}
else {
$el['label'] = "";
}
}
// Display-only (frozen) elements
if (!empty($el['frozen'])) {
if ($element->getAttribute('data-api-entity') && $element->getAttribute('data-entity-value')) {
$this->renderFrozenEntityRef($el, $element);
}
$el['html'] = '' . $el['html'] . '';
}
// Active form elements
else {
if ($element->getType() == 'select' && $element->getAttribute('data-option-edit-path')) {
$this->addOptionsEditLink($el, $element);
}
if ($element->getType() == 'group' && $element->getAttribute('allowClear')) {
$this->appendUnselectButton($el, $element);
}
}
return $el;
}
/**
* Update the attributes of this element and add a few CiviCRM
* based attributes so we can style this form element better
*
*
* @param HTML_QuickForm_element $element
* @param bool $required
* Whether an element is required.
* @param string $error
* Error associated with the element.
*
*/
public static function updateAttributes(&$element, $required, $error) {
// lets create an id for all input elements, so we can generate nice label tags
// to make it nice and clean, we'll just use the elementName if it is non null
$attributes = array();
if (!$element->getAttribute('id')) {
$name = $element->getAttribute('name');
if ($name) {
$attributes['id'] = str_replace(array(']', '['),
array('', '_'),
$name
);
}
}
$class = $element->getAttribute('class');
$type = $element->getType();
if (!$class) {
if ($type == 'text') {
$size = $element->getAttribute('size');
if (!empty($size)) {
$class = CRM_Utils_Array::value($size, self::$_sizeMapper);
}
}
}
if ($type == 'select' && $element->getAttribute('multiple')) {
$type = 'multiselect';
}
// Add widget-specific class
if (!$class || strpos($class, 'crm-form-') === FALSE) {
$class = ($class ? "$class " : '') . 'crm-form-' . $type;
}
elseif (strpos($class, 'crm-form-entityref') !== FALSE) {
self::preProcessEntityRef($element);
}
elseif (strpos($class, 'crm-form-contact-reference') !== FALSE) {
self::preprocessContactReference($element);
}
if ($required) {
$class .= ' required';
}
if ($error) {
$class .= ' error';
}
$attributes['class'] = $class;
$element->updateAttributes($attributes);
}
/**
* Convert IDs to values and format for display.
*
* @param HTML_QuickForm_element $field
*/
public static function preProcessEntityRef($field) {
$val = $field->getValue();
// Temporarily convert string values to an array
if (!is_array($val)) {
// Try to auto-detect method of serialization
$val = strpos($val, ',') ? explode(',', str_replace(', ', ',', $val)) : (array) CRM_Utils_Array::explodePadded($val);
}
if ($val) {
$entity = $field->getAttribute('data-api-entity');
// Get api params, ensure it is an array
$params = $field->getAttribute('data-api-params');
$params = $params ? json_decode($params, TRUE) : array();
$result = civicrm_api3($entity, 'getlist', array('id' => $val) + $params);
if ($field->isFrozen()) {
// Prevent js from treating frozen entityRef as a "live" field
$field->removeAttribute('class');
}
if (!empty($result['values'])) {
$field->setAttribute('data-entity-value', json_encode($result['values']));
}
// CRM-15803 - Remove invalid values
$val = array_intersect($val, CRM_Utils_Array::collect('id', $result['values']));
}
// Convert array values back to a string
$field->setValue(implode(',', $val));
}
/**
* Render entity references as text.
* If user has permission, format as link (for now limited to contacts).
*
* @param array $el
* @param HTML_QuickForm_element $field
*/
public function renderFrozenEntityRef(&$el, $field) {
$entity = $field->getAttribute('data-api-entity');
$vals = json_decode($field->getAttribute('data-entity-value'), TRUE);
$display = array();
// Custom fields of type contactRef store their data in a slightly different format
if ($field->getAttribute('data-crm-custom') && $entity == 'contact') {
$vals = array(array('id' => $vals['id'], 'label' => $vals['text']));
}
foreach ($vals as $val) {
// Format contact as link
if ($entity == 'contact' && CRM_Contact_BAO_Contact_Permission::allow($val['id'], CRM_Core_Permission::VIEW)) {
$url = CRM_Utils_System::url("civicrm/contact/view", array('reset' => 1, 'cid' => $val['id']));
$val['label'] = '' . $val['label'] . '';
}
$display[] = $val['label'];
}
$el['html'] = implode('; ', $display) . '';
}
/**
* Pre-fill contact name for a custom field of type ContactReference
*
* Todo: Migrate contact reference fields to use EntityRef
*
* @param HTML_QuickForm_element $field
*/
public static function preprocessContactReference($field) {
$val = $field->getValue();
if ($val && is_numeric($val)) {
$list = array_keys(CRM_Core_BAO_Setting::valueOptions(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'contact_reference_options'
), '1');
$return = array_unique(array_merge(array('sort_name'), $list));
$contact = civicrm_api('contact', 'getsingle', array('id' => $val, 'return' => $return, 'version' => 3));
if (!empty($contact['id'])) {
$view = array();
foreach ($return as $fld) {
if (!empty($contact[$fld])) {
$view[] = $contact[$fld];
}
}
$field->setAttribute('data-entity-value', json_encode(array(
'id' => $contact['id'],
'text' => implode(' :: ', $view),
)));
}
}
}
/**
* @param array $el
* @param HTML_QuickForm_element $field
*/
public function addOptionsEditLink(&$el, $field) {
if (CRM_Core_Permission::check('administer CiviCRM')) {
// NOTE: $path is used on the client-side to know which option lists need rebuilding,
// that's why we need that bit of data both in the link and in the form element
$path = $field->getAttribute('data-option-edit-path');
// NOTE: If we ever needed to support arguments in this link other than reset=1 we could split $path here if it contains a ?
$url = CRM_Utils_System::url($path, 'reset=1');
$el['html'] .= ' ';
}
}
/**
* @param array $el
* @param HTML_QuickForm_element $field
*/
public function appendUnselectButton(&$el, $field) {
// Initially hide if not needed
// Note: visibility:hidden prevents layout jumping around unlike display:none
$display = $field->getValue() !== NULL ? '' : ' style="visibility:hidden;"';
$el['html'] .= ' ';
}
}