*/ /** * patForms Elemenbt: Keyvaluepair * * Set Key-Value-Pair-List * * @version 0.1.0 * @package Wombat * @subpackage patForms */ class patForms_Element_Keyvaluepair extends patForms_Element { /** * Stores the name of the element - this is used mainly by the patForms * error management and should be set in every element class. * @var string */ public $elementName = 'Keyvaluepair'; /** * element type to create HTML output * @var array */ public $elementType = array('html' => 'input'); /** * Kev Value Pair * @var WBDatasource_KeyValuePair */ private $kvp; /** * List of collected key value pairs * @var array */ private $kvpList = array(); /** * set here which attributes you want to include in the element if you want to use * the {@link patForms_Element::convertDefinition2Attributes()} method to automatically * convert the values from your element definition into element attributes. * * @see patForms_Element::convertDefinition2Attribute() * @var array */ public $attributeDefinition = array( 'id' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array('html'), ), 'name' => array( 'required' => true, 'format' => 'string', 'outputFormats' => array('html'), 'modifiers' => array('insertSpecials' => array()), ), 'type' => array( 'required' => false, 'format' => 'string', 'default' => 'file', 'outputFormats' => array('html'), ), 'title' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array('html'), 'modifiers' => array('insertSpecials' => array()), ), 'description' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array(), 'modifiers' => array('insertSpecials' => array()), ), 'label' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array(), ), 'display' => array( 'required' => false, 'format' => 'string', 'default' => 'yes', 'outputFormats' => array(), ), 'edit' => array( 'required' => false, 'format' => 'string', 'default' => 'yes', 'outputFormats' => array(), ), 'required' => array( 'required' => false, 'format' => 'string', 'default' => 'yes', 'outputFormats' => array(), ), 'value' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array(), ), 'default' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array(), ), 'style' => array( 'required' => false, 'outputFormats' => array('html'), 'format' => 'string', ), 'class' => array( 'required' => false, 'outputFormats' => array('html'), 'format' => 'string', ), 'onchange' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array('html'), 'modifiers' => array('insertSpecials' => array() ), ), 'onclick' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array('html'), 'modifiers' => array('insertSpecials' => array()), ), 'onfocus' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array('html'), 'modifiers' => array('insertSpecials' => array()), ), 'onmouseover' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array('html'), 'modifiers' => array('insertSpecials' => array()), ), 'onmouseout' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array('html'), 'modifiers' => array('insertSpecials' => array()), ), 'onblur' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array('html'), 'modifiers' => array('insertSpecials' => array()), ), 'accesskey' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array('html'), ), 'position' => array( 'required' => false, 'format' => 'int', 'outputFormats' => array(), ), 'tabindex' => array( 'required' => false, 'format' => 'int', 'outputFormats' => array('html'), ), 'format' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array(), ), 'disabled' => array( 'required' => false, 'format' => 'string', 'default' => 'no', 'outputFormats' => array('html'), ), 'domain' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array(), ), 'selectkeylabel' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array(), ), 'keylabel' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array(), ), 'valuelabel' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array(), ), 'newkeylabel' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array(), ), ); /** * Initialize validation codes using gettext * * Overwrite this function to add element's error codes * * @return bool $success Always returns true. * @see $attributeDefaults */ public function loadValidatiorErrorCodes() { $this->validatorErrorCodes = array( 1 => patI18n::dgettext('wombat', 'This field is required, please complete it.') ); // translate default attribute values $this->attributeDefinition['selectkeylabel']['default'] = patI18n::dgettext('wombat', 'Select key'); $this->attributeDefinition['keylabel']['default'] = patI18n::dgettext('wombat', 'Key'); $this->attributeDefinition['valuelabel']['default'] = patI18n::dgettext('wombat', 'Value'); $this->attributeDefinition['newkeylabel']['default'] = patI18n::dgettext('wombat', 'Enter new key'); return true; } /** * element creation method for the 'HTML' format in the 'default' form mode. * * @access public * @param mixed value of the element * @return mixed $element The element, or false if failed. */ public function serializeHtmlDefault($value) { $this->attributes['value'] = $value; // editable or not? if (isset($this->attributes['edit']) && $this->attributes['edit'] == 'no') { return $this->serializeHtmlReadonly($value); } $keys = $this->getKVPKeys(); if (empty($this->kvpList)) { $kvlist = $this->getKVPList($value); } else { $kvlist = $this->kvpList; $keys = array_merge($keys, array_keys($kvlist)); } sort($keys); $id = $this->attributes['id']; WBHtml_JS::add('WB/Form'); WBHtml_JS::add('WB/Form/Element'); WBHtml_JS::add('WB/Form/Element/Keyvaluepair'); WBHtml_JS::add(sprintf('$("%s").keyvalue = new WB.Form.Element.Keyvaluepair("%1$s");', $id), WBHtml_JS::AREA_FOOT); $atts = $this->getAttributesFor($this->getFormat()); $html = array(); $html[] = $this->createTag('div', 'opening', $atts); // keep aktual value in hidden input field $atts = array( 'class' => 'value', 'type' => 'hidden', 'name' => $this->attributes['name'], 'value' => $value ); $html[] = $this->createTag('input', 'full', $atts); $keyOpts = array(); $keyOpts[] = array( 'label' => $this->getAttribute('selectkeylabel'), 'value' => '__empty', 'class' => 'select', ); $keyOpts[] = array( 'label' => $this->getAttribute('newkeylabel'), 'value' => '__input', 'class' => 'input', ); foreach ($keys as $k) { $keyOpts[] = array( 'label' => $k, 'value' => $k, 'class' => 'select', ); } $i = 0; $atts = array( 'class' => 'keyvaluepairinput' ); $html[] = $this->createTag('div', 'opening', $atts); foreach ($kvlist as $k => $v) { $this->createPairInput($html, $keyOpts, $i, $k, $v); ++$i; } $html[] = $this->createTag('div', 'closing'); $atts = array( 'class' => 'keyvaluepairprototype', 'style' => 'display:none;' ); $html[] = $this->createTag('div', 'opening', $atts); $this->createPairInput($html, $keyOpts, 'x', '', ''); $html[] = $this->createTag('div', 'closing'); // add button $atts = array( 'class' => 'add', 'title' => patI18n::dgettext('wombat', 'Add key value pair'), 'onclick' => sprintf('$(\'%s\').keyvalue.add(this.parentNode);', $id) ); $html[] = $this->createTag('span', 'full', $atts, patI18n::dgettext('wombat', 'add')); $html[] = $this->createTag('div', 'closing'); return implode("\n", $html); } /** * Create key-value pair input form * * Build HTML snippet and append it to $html array. * * @param array $html * @param array $keyOpt Options for select input * @param int $i number of key-value-pair * @param string $k key * @param string $v value */ private function createPairInput(&$html, $keyOpts, $i, $k, $v) { $id = $this->attributes['id']; // key value pairs $atts = array( 'class' => 'keyvaluepair', 'no' => $i ); $html[] = $this->createTag('div', 'opening', $atts); $atts = array( 'class' => 'key', ); $html[] = $this->createTag('div', 'opening', $atts); // key select $atts = array( 'class' => 'keyselect', ); $html[] = $this->createTag('span', 'opening', $atts); $html[] = $this->createTag('label', 'full', array(), $this->getAttribute('keylabel')); $atts = array( 'title' => $this->getAttribute('keylabel'), 'name' => sprintf('%s-keyselect-%s', $id, $i), 'onchange' => sprintf('$(\'%s\').keyvalue.changeKey(this);', $id) ); $html[] = $this->createTag('select', 'opening', $atts); foreach ($keyOpts as $kopt) { if ($kopt['value'] == $k) { $kopt['selected'] = 'selected'; } $label = $kopt['label']; unset($kopt['label']); $html[] = $this->createTag('option', 'full', $kopt, $label); } $html[] = $this->createTag('select', 'closing'); $html[] = $this->createTag('span', 'closing'); // key input $atts = array( 'class' => 'keyinput', 'style' => 'display:none;' ); $html[] = $this->createTag('span', 'opening', $atts); $atts = array( 'type' => 'text', 'value' => '', 'name' => sprintf('%s-keyinput-%s', $id, $i), ); $html[] = $this->createTag('input', 'full', $atts); $html[] = $this->createTag('span', 'closing'); $html[] = $this->createTag('div', 'closing'); $atts = array( 'class' => 'value', ); $html[] = $this->createTag('div', 'opening', $atts); // value input $atts = array( 'class' => 'valueinput', ); $html[] = $this->createTag('span', 'opening', $atts); $html[] = $this->createTag('label', 'full', array(), $this->getAttribute('valuelabel')); $atts = array( 'type' => 'text', 'value' => $v, 'name' => sprintf('%s-value-%s', $id, $i) ); $html[] = $this->createTag('input', 'full', $atts); $html[] = $this->createTag('span', 'closing'); $html[] = $this->createTag('div', 'closing'); // delete button $atts = array( 'class' => 'remove', 'title' => patI18n::dgettext('wombat', 'Remove this key value pair'), 'onclick' => sprintf('$(\'%s\').keyvalue.remove(this);', $id) ); $html[] = $this->createTag('span', 'full', $atts, patI18n::dgettext('wombat', 'remove')); $html[] = $this->createTag('div', 'closing'); } /** * element creation method for the 'HTML' format in the 'readonly' form mode. * Very simple; just returns the stored element value. * * @access public * @param mixed value of the element * @return string $value The element's value * @todo implement this funktion */ public function serializeHtmlReadonly($value) { $html = array(); $atts = array( 'class' => $this->attributes['class'] ); $html[] = $this->createTag('div', 'opening', $atts); $html[] = $this->createHiddenTag($value); $html[] = $this->createTag('div', 'closing'); return implode("\n", $html); } /** * validates the element. * * Verify file upload * * @param stringd $value of the element * @return bool $isValid True if element could be validated, false otherwise. */ public function validateElement($value) { $required = false; $name = $this->attributes['name']; $id = $this->attributes['id']; // store the required flag for easy access if (isset($this->attributes['required']) && $this->attributes['required'] == 'yes') { $required = true; } $this->collectDataFromRequest($id); if (empty($this->kvpList) && $required) { $this->addValidationError(1); return false; } if (empty($value)) { $value = '__new'; } $this->initKVP(); $this->value = $this->kvp->set($this->kvpList, $value); return true; } /** * Collect values * * Walk through request data and collect input acording to selected key * * @param string $id */ private function collectDataFromRequest($id) { // magic quotes $mq = get_magic_quotes_gpc(); $data = array(); $keyS = $id . '-keyselect-'; $keySl = strlen($keyS); $keyI = $id . '-keyinput-'; $valI = $id . '-value-'; foreach ($_REQUEST as $k => $v) { if (0 != strncmp($k, $keyS, $keySl)) { continue; } if ($v == '__empty') { continue; } $no = substr($k, $keySl); if ('x' == $no) { continue; } $key = $v; if ($v == '__input') { $key = $_REQUEST[$keyI . $no]; } if ($mq) { $key = stripslashes($key); } if (empty($key)) { continue; } $value = $_REQUEST[$valI . $no]; if ($mq) { $value = stripslashes($value); } if (empty($value)) { continue; } $data[$key] = $value; } $this->kvpList = $data; } private function getKVPKeys() { $this->initKVP(); return $this->kvp->getKeys(); } private function getKVPList($id) { $this->initKVP(); return $this->kvp->get($id); } private function initKVP() { if ($this->kvp) { return; } $this->kvp = WBClass::create('WBDatasource_KeyValuePair'); $this->kvp->setDomain($this->attributes['domain']); $this->kvp->switchTranslation(false); } }