*/ if (!class_exists('patForms_Element', false)) { WBClass::load('patForms_Element'); } /** * patForms Elemenbt: Wxml * * WYSIWIG editor for Wombat XML format. * * * @version 0.1.0 * @package Wombat * @subpackage patForms */ class patForms_Element_Wxml 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 = 'Wxml'; /** * Attribute definition * * @see patForms_Element::convertDefinition2Attribute() */ 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()), ), 'title' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array(), 'modifiers' => array('insertSpecials' => array()), ), 'toolbar' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array(), 'default' => '__default', 'modifiers' => array('insertSpecials' => array()), ), 'policy' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array(), 'default' => '__default', 'modifiers' => array('insertSpecials' => array()), ), /* 'placeholder' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array('html'), 'modifiers' => array('insertSpecials' => array()), ), */ 'description' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array(), 'modifiers' => array('insertSpecials' => array()), ), 'default' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array(), ), 'label' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array(), 'modifiers' => array('insertSpecials' => array()), ), 'edit' => array( 'required' => false, 'format' => 'string', 'default' => 'yes', 'outputFormats' => array(), ), 'display' => 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(), ), 'style' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array('html'), ), 'class' => array( 'required' => false, 'format' => 'string', 'outputFormats' => array('html'), ), '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'), ), 'maxlength' => array( 'required' => false, 'format' => 'int', 'outputFormats' => array(), ), 'minlength' => array( 'required' => false, 'format' => 'int', 'outputFormats' => array(), ), 'disabled' => array( 'required' => false, 'format' => 'string', 'default' => 'no', 'outputFormats' => array('html'), ), ); /** * Template engine * @var patTemplate */ private $tmpl; /** * Policy Configuration * @var WBConfig */ private $policy; /** * @var WBMarkup_Scanner */ private $scan; /** * @var WBMarkup_Handler_Wxml2Xml */ private $hdlX; /** * @var WBMarkup_Handler_Validator */ private $hdlV; /** * Constructor * * Call parent constructor and add filter to transform Wxml HTML to and * from XML * * @param $format */ public function __construct($format = false) { $this->tmpl = WBClass::create('patTemplate'); $filter = patForms::createFilter('XmlWxml'); $this->applyFilter($filter); parent::__construct($format); } /** * Initialize validation codes using gettext * * @return bool Always returns true. * @see $attributeDefaults */ function loadValidatiorErrorCodes() { $this->validatorErrorCodes = array( 1 => patI18n::dgettext('patForms', 'This field is required, please complete it.'), 2 => patI18n::dgettext('patForms', 'Failed to read text input'), 3 => patI18n::dgettext('patForms', 'The value is shorter than the minimum length of [MINLENGTH].'), 4 => patI18n::dgettext('patForms', 'The value is longer than the maximum length of [MAXLENGTH].'), //3 => patI18n::dgettext('patForms', 'Text length [LENGTH] is shorter than the minimum length of [MINLENGTH].'), //4 => patI18n::dgettext('patForms', 'Text length [LENGTH] is longer than the maximum length of [MAXLENGTH].') ); return true; } /** * Element creation method for the 'HTML' format in the 'default' form mode. * * @param mixed value of the element * @return mixed The element's html string, or false if failed. */ public function serializeHtmlDefault($value) { $html = array(); // the surrounding tag $atts = $this->getAttributesFor($this->getFormat()); $atts['class'] .= ' wb-wxml'; $html[] = $this->createTag('div', 'opening', $atts); if ('yes' == $this->getAttribute('disabled')) { $this->serilizeHtmlDefaultDisabled($html, $value); } else { $this->serilizeHtmlDefaultEditor($html, $value); } $html[] = $this->createTag('div', 'closing'); return implode("\n", $html); } /** * Editor is enabled * * @param array $html * @param string $value */ private function serilizeHtmlDefaultEditor(&$html, $value) { // the toolbar $this->tmpl->readTemplatesFromInput('Wxml/editor/toolbar/' . $this->getAttribute('toolbar') . '.tmpl'); $atts = array( 'class' => 'btn-toolbar', 'data-role' => 'editor-toolbar', 'data-target' => sprintf('#%s div.wb-wxml-editor', $this->getAttribute('id')) ); $html[] = $this->createTag('div', 'opening', $atts); $html[] = $this->tmpl->getParsedTemplate('snippet_wxml_toolbar'); $html[] = $this->createTag('div', 'closing'); // the editor itself $atts = array( 'class' => 'wb-wxml-editor', 'name' => $this->getAttribute('name'), 'title' => $this->getAttribute('title') ); $html[] = $this->createTag('div', 'opening', $atts); $html[] = $value; $html[] = $this->createTag('div', 'closing'); // hidden textarea $atts['hidden'] = 'yes'; $html[] = $this->createTag('textarea', 'opening', $atts); $html[] = $value; $html[] = $this->createTag('textarea', 'closing'); WBClass::load('WBHtml_JS'); $js = 'new WB.Form.Element.Wxml("'.$this->getAttribute('id').'");'; WBHtml_JS::add($js, WBHtml_JS::AREA_FOOT); } /** * Editor is disabled * * * @todo display proper HTML * @param array $html * @param string $value */ private function serilizeHtmlDefaultDisabled(&$html, $value) { // convert value from WXML to HTML $html[] = $value; } /** * Validates the element. * * @param mixed value of the element * @return bool true if element could be validated, false otherwise. */ public function validateElement($value) { if ('yes' == $this->attributes['disabled']) { $this->value = $value; return true; } $required = false; $empty = false; // store the required flag for easy access if (isset($this->attributes['required']) && $this->attributes['required'] == 'yes') { $required = true; } if (strlen($value) == 0) { $empty = true; } if ($empty && $required) { $this->addValidationError(1); return false; } if ($empty && !$required) { return true; } // is it a string? if (!is_string($value)) { $this->addValidationError(2); return false; } // remove garbage $value = trim($value); // char length $valueTagFree = strip_tags($value); $valueTagFreeLen = strlen($valueTagFree); // minlength if (isset($this->attributes['minlength']) && $valueTagFreeLen < $this->attributes['minlength']) { $this->addValidationError(3, array('minlength' => $this->attributes['minlength'], 'length' => $valueTagFreeLen)); return false; } // maxlength if (isset($this->attributes['maxlength']) && $valueTagFreeLen > $this->attributes['maxlength']) { $this->addValidationError(4, array('maxlength' => $this->attributes['maxlength'], 'length' => $valueTagFreeLen)); return false; } // remove duplicates $value = str_replace('
', '
', $value); $value = str_replace('


', '

', $value); $value = str_replace('

', '

', $value); $value = str_replace('

', '
', $value); $value = str_replace('

', '

', $value); // force P-tags $tmp = strip_tags($value, '

'); if ($tmp == $value) { $value = '

' . str_replace('
', '

', $value) . '

'; $this->value = $value; } $this->scan = WBClass::create('WBMarkup_Scanner'); $value = $this->value2xml($value); return $this->validateXml($value); } /** * Convert Wxml-value to internal XML * * @param string $value */ private function value2xml($value) { $this->hdlX = WBClass::create('WBMarkup_Handler_Wxml2Xml'); $this->scan->setHandler($this->hdlX); $this->scan->scan($value); return $this->hdlX->getParsedContent(); } /** * Validate XML verlue * * In case validation failed, errors are added * * @param string $value xml + @return bool true if Valid */ private function validateXml($value) { WBClass::load('WBMarkup_Handler_Validator'); $this->hdlV = WBClass::create('WBMarkup_Handler_Validator'); $this->hdlV->setPolicy($this->getAttribute('policy')); $this->scan->setHandler($this->hdlV); $this->scan->scan($value); $errors = $this->hdlV->getErrors(); if (empty($errors)) { return true; } foreach ($errors as $e) { $this->validationErrors[] = array( 'element' => $this->getElementName(), 'code' => $e['code'], 'message' => $e['msg'] ); } return false; } }