├── .gitignore ├── README.md ├── composer.json └── lib └── HTML ├── Common.php ├── QuickForm.php └── QuickForm ├── Error.php ├── Renderer.php ├── Renderer ├── Array.php ├── ArraySmarty.php ├── Default.php ├── ITDynamic.php ├── ITStatic.php ├── Object.php ├── ObjectFlexy.php ├── QuickHtml.php └── Tableless.php ├── Rule.php ├── Rule ├── Callback.php ├── Compare.php ├── Email.php ├── Range.php ├── Regex.php └── Required.php ├── RuleRegistry.php ├── advcheckbox.php ├── autocomplete.php ├── button.php ├── checkbox.php ├── date.php ├── element.php ├── file.php ├── group.php ├── header.php ├── hidden.php ├── hiddenselect.php ├── hierselect.php ├── html.php ├── image.php ├── input.php ├── link.php ├── password.php ├── radio.php ├── reset.php ├── select.php ├── static.php ├── submit.php ├── text.php ├── textarea.php ├── utils.php └── xbutton.php /.gitignore: -------------------------------------------------------------------------------- 1 | /.project 2 | /.buildpath 3 | /.settings 4 | /vendor 5 | composer.phar 6 | composer.lock 7 | phpunit.xml 8 | .DS_Store 9 | *~ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | quickform 2 | ========= 3 | 4 | Forward compatible fork of HTML_QuickForm 5 | 6 | This package is intended mainly as a drop-in replacement for existing installations of `HTML_Quickform`. See http://pear.php.net/manual/en/package.html.html-quickform.php for documentation. 7 | 8 | The main differences to the original package are: 9 | 10 | - Compatible with PHP 5.4 and newer: It will run without producing warnings or deprecated notices 11 | - No PEAR dependencies: `HTML_Common` is replaced by a bundled version, and `PEAR_Error`s are replaced by exceptions 12 | - Support for Composer autoloading: All `include` statements have been removed in favor of classmap autoloading 13 | - Upon popular request, `HTML_QuickForm_Renderer_Tableless` has been included and is available out of the box (PHP only, you need 14 | to supply your own stylesheet) 15 | 16 | ### API Compatibility 17 | 18 | - Some calls are listed in the PEAR documentation as static, but making them statically callable without warnings would require significant rewrites and might break other use cases. So if you get errors about assuming `$this` from an incompatible context, just change your calls to nonstatic ones. 19 | 20 | - `HTML_QuickForm_Renderer::renderHidden` has a slightly changed signature and takes three arguments now: `&$element, $required, $error`, exactly like `HTML_QuickForm_Renderer::renderElement`. This means it is now possible to render validation errors on hidden fields, which is useful for example for CSRF fields. Custom renderer implementations need to add the two arguments to the method's signature, but actual implementations do not need to be changed. 21 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "openpsa/quickform", 3 | "type": "library", 4 | "description": "PHP 5.4 compatible fork of HTML_QuickForm", 5 | "keywords": ["form", "quickform"], 6 | "license": "PHP-3.01", 7 | "authors": [ 8 | { 9 | "name": "Andreas Flack", 10 | "email": "flack@contentcontrol-berlin.de", 11 | "homepage": "http://www.contentcontrol-berlin.de/" 12 | } 13 | ], 14 | "require": { 15 | "php": ">5.4" 16 | }, 17 | "autoload": { 18 | "classmap": ["lib"] 19 | }, 20 | "extra": { 21 | "branch-alias": { 22 | "dev-master": "3.4.x-dev" 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lib/HTML/Common.php: -------------------------------------------------------------------------------- 1 | 7 | * @copyright 2001-2009 The PHP Group 8 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 9 | */ 10 | 11 | /** 12 | * Base class for all HTML classes 13 | * 14 | * @package HTML_Common 15 | * @author Adam Daniel 16 | */ 17 | abstract class HTML_Common 18 | { 19 | /** 20 | * Associative array of attributes 21 | * 22 | * @var array 23 | * @access private 24 | */ 25 | var $_attributes = array(); 26 | 27 | /** 28 | * Tab offset of the tag 29 | * 30 | * @var int 31 | * @access private 32 | */ 33 | var $_tabOffset = 0; 34 | 35 | /** 36 | * Tab string 37 | * 38 | * @var string 39 | * @access private 40 | */ 41 | var $_tab = "\11"; 42 | 43 | /** 44 | * Contains the line end string 45 | * 46 | * @var string 47 | * @access private 48 | */ 49 | var $_lineEnd = "\12"; 50 | 51 | /** 52 | * HTML comment on the object 53 | * 54 | * @var string 55 | * @access private 56 | */ 57 | var $_comment = ''; 58 | 59 | /** 60 | * Class constructor 61 | * 62 | * @param mixed $attributes Associative array of table tag attributes 63 | * or HTML attributes name="value" pairs 64 | * @param int $tabOffset Indent offset in tabs 65 | */ 66 | public function __construct($attributes = null, $tabOffset = 0) 67 | { 68 | $this->setAttributes($attributes); 69 | $this->setTabOffset($tabOffset); 70 | } 71 | 72 | /** 73 | * Returns the current API version 74 | * 75 | * @returns double 76 | */ 77 | public function apiVersion() 78 | { 79 | return 1.7; 80 | } 81 | 82 | /** 83 | * Returns the lineEnd 84 | * 85 | * @access private 86 | * @return string 87 | */ 88 | function _getLineEnd() 89 | { 90 | return $this->_lineEnd; 91 | } 92 | 93 | /** 94 | * Returns a string containing the unit for indenting HTML 95 | * 96 | * @access private 97 | * @return string 98 | */ 99 | function _getTab() 100 | { 101 | return $this->_tab; 102 | } 103 | 104 | /** 105 | * Returns a string containing the offset for the whole HTML code 106 | * 107 | * @return string 108 | * @access private 109 | */ 110 | function _getTabs() 111 | { 112 | return str_repeat($this->_getTab(), $this->_tabOffset); 113 | } 114 | 115 | /** 116 | * Returns an HTML formatted attribute string 117 | * 118 | * @param array $attributes 119 | * @return string 120 | * @access private 121 | */ 122 | function _getAttrString($attributes) 123 | { 124 | $strAttr = ''; 125 | 126 | if (is_array($attributes)) { 127 | $charset = self::charset(); 128 | foreach ($attributes as $key => $value) { 129 | if (is_scalar($value)) { 130 | $strAttr .= ' ' . $key . '="' . htmlspecialchars($value, ENT_COMPAT, $charset) . '"'; 131 | } 132 | } 133 | } 134 | return $strAttr; 135 | } 136 | 137 | /** 138 | * Returns a valid atrributes array from either a string or array 139 | * 140 | * @param mixed $attributes Either a typical HTML attribute string or an associative array 141 | * @access private 142 | * @return array 143 | */ 144 | function _parseAttributes($attributes) 145 | { 146 | if (is_array($attributes)) { 147 | $ret = array(); 148 | foreach ($attributes as $key => $value) { 149 | if (is_int($key)) { 150 | $key = $value = strtolower($value); 151 | } else { 152 | $key = strtolower($key); 153 | } 154 | $ret[$key] = $value; 155 | } 156 | return $ret; 157 | 158 | } elseif (is_string($attributes)) { 159 | $preg = "/(([A-Za-z_:]|[^\\x00-\\x7F])([A-Za-z0-9_:.-]|[^\\x00-\\x7F])*)" . 160 | "([ \\n\\t\\r]+)?(=([ \\n\\t\\r]+)?(\"[^\"]*\"|'[^']*'|[^ \\n\\t\\r]*))?/"; 161 | if (preg_match_all($preg, $attributes, $regs)) { 162 | for ($counter=0; $counter $value) { 212 | $attr1[$key] = $value; 213 | } 214 | } 215 | 216 | /** 217 | * Removes the given attribute from the given array 218 | * 219 | * @param string $attr Attribute name 220 | * @param array $attributes Attribute array 221 | * @access private 222 | * @return void 223 | */ 224 | function _removeAttr($attr, &$attributes) 225 | { 226 | $attr = strtolower($attr); 227 | if (isset($attributes[$attr])) { 228 | unset($attributes[$attr]); 229 | } 230 | } 231 | 232 | /** 233 | * Returns the value of the given attribute 234 | * 235 | * @param string $attr Attribute name 236 | * @return string|null returns null if an attribute does not exist 237 | */ 238 | public function getAttribute($attr) 239 | { 240 | $attr = strtolower($attr); 241 | if (isset($this->_attributes[$attr])) { 242 | return $this->_attributes[$attr]; 243 | } 244 | return null; 245 | } 246 | 247 | /** 248 | * Sets the value of the attribute 249 | * 250 | * @param string Attribute name 251 | * @param string Attribute value (will be set to $name if omitted) 252 | */ 253 | public function setAttribute($name, $value = null) 254 | { 255 | $name = strtolower($name); 256 | if (is_null($value)) { 257 | $value = $name; 258 | } 259 | $this->_attributes[$name] = $value; 260 | } 261 | 262 | /** 263 | * Sets the HTML attributes 264 | * 265 | * @param mixed $attributes Either a typical HTML attribute string or an associative array 266 | */ 267 | public function setAttributes($attributes) 268 | { 269 | $this->_attributes = $this->_parseAttributes($attributes); 270 | } 271 | 272 | /** 273 | * Returns the assoc array (default) or string of attributes 274 | * 275 | * @param bool Whether to return the attributes as string 276 | * @return mixed attributes 277 | */ 278 | public function getAttributes($asString = false) 279 | { 280 | if ($asString) { 281 | return $this->_getAttrString($this->_attributes); 282 | } else { 283 | return $this->_attributes; 284 | } 285 | } 286 | 287 | /** 288 | * Updates the passed attributes without changing the other existing attributes 289 | * 290 | * @param mixed $attributes Either a typical HTML attribute string or an associative array 291 | */ 292 | function updateAttributes($attributes) 293 | { 294 | $this->_updateAttrArray($this->_attributes, $this->_parseAttributes($attributes)); 295 | } 296 | 297 | /** 298 | * Removes an attribute 299 | * 300 | * @param string $attr Attribute name 301 | */ 302 | public function removeAttribute($attr) 303 | { 304 | $this->_removeAttr($attr, $this->_attributes); 305 | } 306 | 307 | /** 308 | * Sets the line end style to Windows, Mac, Unix or a custom string. 309 | * 310 | * @param string $style "win", "mac", "unix" or custom string. 311 | */ 312 | public function setLineEnd($style) 313 | { 314 | switch ($style) { 315 | case 'win': 316 | $this->_lineEnd = "\15\12"; 317 | break; 318 | case 'unix': 319 | $this->_lineEnd = "\12"; 320 | break; 321 | case 'mac': 322 | $this->_lineEnd = "\15"; 323 | break; 324 | default: 325 | $this->_lineEnd = $style; 326 | } 327 | } 328 | 329 | /** 330 | * Sets the tab offset 331 | * 332 | * @param int $offset 333 | */ 334 | public function setTabOffset($offset) 335 | { 336 | $this->_tabOffset = $offset; 337 | } 338 | 339 | /** 340 | * Returns the tabOffset 341 | * 342 | * @return int 343 | */ 344 | public function getTabOffset() 345 | { 346 | return $this->_tabOffset; 347 | } 348 | 349 | /** 350 | * Sets the string used to indent HTML 351 | * 352 | * @param string $string String used to indent ("\11", "\t", ' ', etc.). 353 | */ 354 | public function setTab($string) 355 | { 356 | $this->_tab = $string; 357 | } 358 | 359 | /** 360 | * Sets the HTML comment to be displayed at the beginning of the HTML string 361 | * 362 | * @param string 363 | */ 364 | public function setComment($comment) 365 | { 366 | $this->_comment = $comment; 367 | } 368 | 369 | /** 370 | * Returns the HTML comment 371 | * 372 | * @return string 373 | */ 374 | public function getComment() 375 | { 376 | return $this->_comment; 377 | } 378 | 379 | /** 380 | * Abstract method. Must be extended to return the objects HTML 381 | * 382 | * @return string 383 | */ 384 | abstract function toHtml(); 385 | 386 | /** 387 | * Displays the HTML to the screen 388 | */ 389 | public function display() 390 | { 391 | print $this->toHtml(); 392 | } 393 | 394 | /** 395 | * Sets the charset to use by htmlspecialchars() function 396 | * 397 | * Since this parameter is expected to be global, the function is designed 398 | * to be called statically: 399 | * 400 | * HTML_Common::charset('utf-8'); 401 | * 402 | * or 403 | * 404 | * $charset = HTML_Common::charset(); 405 | * 406 | * 407 | * @param string New charset to use. Omit if just getting the 408 | * current value. Consult the htmlspecialchars() docs 409 | * for a list of supported character sets. 410 | * @return string Current charset 411 | */ 412 | public static function charset($newCharset = null) 413 | { 414 | static $charset = 'ISO-8859-1'; 415 | 416 | if (!is_null($newCharset)) { 417 | $charset = $newCharset; 418 | } 419 | return $charset; 420 | } 421 | } 422 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/Error.php: -------------------------------------------------------------------------------- 1 | 7 | * @author Bertrand Mansion 8 | */ 9 | class HTML_QuickForm_Error extends Exception 10 | { 11 | /** 12 | * Prefix for all error messages 13 | * @var string 14 | */ 15 | var $error_message_prefix = 'QuickForm Error: '; 16 | 17 | /** 18 | * Creates a quickform error exception 19 | * 20 | * @param string $message The error message 21 | * @param int $code The error code 22 | */ 23 | function __construct($message, $code = QUICKFORM_ERROR) 24 | { 25 | if (is_int($code)) { 26 | parent::__construct(HTML_QuickForm::errorMessage($code) . ': ' . $message, $code); 27 | } else { 28 | throw new self("Invalid error code: $code", QUICKFORM_ERROR, $this); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/Renderer.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2001-2011 The PHP Group 6 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 7 | */ 8 | 9 | /** 10 | * An abstract base class for QuickForm renderers 11 | * 12 | * The class implements a Visitor design pattern 13 | * 14 | * @category HTML 15 | * @package HTML_QuickForm 16 | * @author Alexey Borzov 17 | */ 18 | abstract class HTML_QuickForm_Renderer 19 | { 20 | /** 21 | * Called when visiting a form, before processing any form elements 22 | * 23 | * @param HTML_QuickForm a form being visited 24 | */ 25 | abstract public function startForm(&$form); 26 | 27 | /** 28 | * Called when visiting a form, after processing all form elements 29 | * 30 | * @param HTML_QuickForm a form being visited 31 | */ 32 | abstract public function finishForm(&$form); 33 | 34 | /** 35 | * Called when visiting a header element 36 | * 37 | * @param HTML_QuickForm_header a header element being visited 38 | */ 39 | abstract public function renderHeader(&$header); 40 | 41 | /** 42 | * Called when visiting an element 43 | * 44 | * @param HTML_QuickForm_element form element being visited 45 | * @param bool Whether an element is required 46 | * @param string An error message associated with an element 47 | */ 48 | abstract public function renderElement(&$element, $required, $error); 49 | 50 | /** 51 | * Called when visiting a hidden element 52 | * 53 | * @param HTML_QuickForm_element a hidden element being visited 54 | * @param bool Whether an element is required 55 | * @param string An error message associated with an element 56 | */ 57 | abstract public function renderHidden(&$element, $required, $error); 58 | 59 | /** 60 | * Called when visiting a raw HTML/text pseudo-element 61 | * 62 | * Only implemented in Default renderer. Usage of 'html' elements is 63 | * discouraged, templates should be used instead. 64 | * 65 | * @param HTML_QuickForm_html a 'raw html' element being visited 66 | */ 67 | abstract public function renderHtml(&$data); 68 | 69 | /** 70 | * Called when visiting a group, before processing any group elements 71 | * 72 | * @param HTML_QuickForm_group A group being visited 73 | * @param bool Whether a group is required 74 | * @param string An error message associated with a group 75 | */ 76 | abstract public function startGroup(&$group, $required, $error); 77 | 78 | /** 79 | * Called when visiting a group, after processing all group elements 80 | * 81 | * @param HTML_QuickForm_group A group being visited 82 | * @return void 83 | */ 84 | abstract public function finishGroup(&$group); 85 | } 86 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/Renderer/Array.php: -------------------------------------------------------------------------------- 1 | 5 | * @author Adam Daniel 6 | * @author Bertrand Mansion 7 | * @author Thomas Schulz 8 | * @copyright 2001-2011 The PHP Group 9 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 10 | */ 11 | 12 | /** 13 | * A concrete renderer for HTML_QuickForm, makes an array of form contents 14 | * 15 | * Based on old HTML_QuickForm::toArray() code. 16 | * 17 | * The form array structure is the following: 18 | *
 19 |  * array(
 20 |  *   'frozen'           => 'whether the form is frozen',
 21 |  *   'javascript'       => 'javascript for client-side validation',
 22 |  *   'attributes'       => 'attributes for 
tag', 23 | * 'requirednote => 'note about the required elements', 24 | * // if we set the option to collect hidden elements 25 | * 'hidden' => 'collected html of all hidden elements', 26 | * // if there were some validation errors: 27 | * 'errors' => array( 28 | * '1st element name' => 'Error for the 1st element', 29 | * ... 30 | * 'nth element name' => 'Error for the nth element' 31 | * ), 32 | * // if there are no headers in the form: 33 | * 'elements' => array( 34 | * element_1, 35 | * ... 36 | * element_N 37 | * ) 38 | * // if there are headers in the form: 39 | * 'sections' => array( 40 | * array( 41 | * 'header' => 'Header text for the first header', 42 | * 'name' => 'Header name for the first header', 43 | * 'elements' => array( 44 | * element_1, 45 | * ... 46 | * element_K1 47 | * ) 48 | * ), 49 | * ... 50 | * array( 51 | * 'header' => 'Header text for the Mth header', 52 | * 'name' => 'Header name for the Mth header', 53 | * 'elements' => array( 54 | * element_1, 55 | * ... 56 | * element_KM 57 | * ) 58 | * ) 59 | * ) 60 | * ); 61 | *
62 | * 63 | * where element_i is an array of the form: 64 | *
 65 |  * array(
 66 |  *   'name'      => 'element name',
 67 |  *   'value'     => 'element value',
 68 |  *   'type'      => 'type of the element',
 69 |  *   'frozen'    => 'whether element is frozen',
 70 |  *   'label'     => 'label for the element',
 71 |  *   'required'  => 'whether element is required',
 72 |  *   'error'     => 'error associated with the element',
 73 |  *   'style'     => 'some information about element style (e.g. for Smarty)',
 74 |  *   // if element is not a group
 75 |  *   'html'      => 'HTML for the element'
 76 |  *   // if element is a group
 77 |  *   'separator' => 'separator for group elements',
 78 |  *   'elements'  => array(
 79 |  *     element_1,
 80 |  *     ...
 81 |  *     element_N
 82 |  *   )
 83 |  * );
 84 |  * 
85 | * 86 | * @package HTML_QuickForm 87 | * @author Alexey Borzov 88 | * @author Adam Daniel 89 | * @author Bertrand Mansion 90 | * @author Thomas Schulz 91 | */ 92 | class HTML_QuickForm_Renderer_Array extends HTML_QuickForm_Renderer 93 | { 94 | /** 95 | * An array being generated 96 | * 97 | * @var array 98 | */ 99 | protected $_ary; 100 | 101 | /** 102 | * Number of sections in the form (i.e. number of headers in it) 103 | * 104 | * @var integer 105 | */ 106 | protected $_sectionCount; 107 | 108 | /** 109 | * Current section number 110 | * 111 | * @var integer 112 | */ 113 | protected $_currentSection; 114 | 115 | /** 116 | * Array representing current group 117 | * 118 | * @var array 119 | */ 120 | protected $_currentGroup = null; 121 | 122 | /** 123 | * Additional style information for different elements 124 | * 125 | * @var array 126 | */ 127 | private $_elementStyles = array(); 128 | 129 | /** 130 | * true: collect all hidden elements into string; false: process them as usual form elements 131 | * 132 | * @var bool 133 | */ 134 | private $_collectHidden = false; 135 | 136 | /** 137 | * true: render an array of labels to many labels, $key 0 named 'label', the rest "label_$key" 138 | * false: leave labels as defined 139 | * 140 | * @var bool 141 | */ 142 | private $_staticLabels = false; 143 | 144 | /** 145 | * Constructor 146 | * 147 | * @param bool true: collect all hidden elements into string; false: process them as usual form elements 148 | * @param bool true: render an array of labels to many labels, $key 0 to 'label' and the oterh to "label_$key" 149 | */ 150 | public function __construct($collectHidden = false, $staticLabels = false) 151 | { 152 | $this->_collectHidden = $collectHidden; 153 | $this->_staticLabels = $staticLabels; 154 | } 155 | 156 | /** 157 | * Returns the resultant array 158 | * 159 | * @return array 160 | */ 161 | public function toArray() 162 | { 163 | return $this->_ary; 164 | } 165 | 166 | /** 167 | * @inheritDoc 168 | */ 169 | public function startForm(&$form) 170 | { 171 | $this->_ary = array( 172 | 'frozen' => $form->isFrozen(), 173 | 'javascript' => $form->getValidationScript(), 174 | 'attributes' => $form->getAttributes(true), 175 | 'requirednote' => $form->getRequiredNote(), 176 | 'errors' => array() 177 | ); 178 | if ($this->_collectHidden) { 179 | $this->_ary['hidden'] = ''; 180 | } 181 | $this->_currentSection = null; 182 | $this->_sectionCount = 0; 183 | } 184 | 185 | /** 186 | * @inheritDoc 187 | */ 188 | public function renderHeader(&$header) 189 | { 190 | $this->_ary['sections'][$this->_sectionCount] = array( 191 | 'header' => $header->toHtml(), 192 | 'name' => $header->getName() 193 | ); 194 | $this->_currentSection = $this->_sectionCount++; 195 | } 196 | 197 | /** 198 | * @inheritDoc 199 | */ 200 | public function renderElement(&$element, $required, $error) 201 | { 202 | $elAry = $this->_elementToArray($element, $required, $error); 203 | if (!empty($error)) { 204 | $this->_ary['errors'][$elAry['name']] = $error; 205 | } 206 | $this->_storeArray($elAry); 207 | } 208 | 209 | /** 210 | * @inheritDoc 211 | */ 212 | public function renderHidden(&$element, $required, $error) 213 | { 214 | if ($this->_collectHidden) { 215 | $this->_ary['hidden'] .= $element->toHtml() . "\n"; 216 | } else { 217 | $this->renderElement($element, $required, $error); 218 | } 219 | } 220 | 221 | /** 222 | * @inheritDoc 223 | */ 224 | public function startGroup(&$group, $required, $error) 225 | { 226 | $this->_currentGroup = $this->_elementToArray($group, $required, $error); 227 | if (!empty($error)) { 228 | $this->_ary['errors'][$this->_currentGroup['name']] = $error; 229 | } 230 | } 231 | 232 | /** 233 | * @inheritDoc 234 | */ 235 | public function finishGroup(&$group) 236 | { 237 | $this->_storeArray($this->_currentGroup); 238 | $this->_currentGroup = null; 239 | } 240 | 241 | /** 242 | * Creates an array representing an element 243 | * 244 | * @param HTML_QuickForm_element element being processed 245 | * @param bool Whether an element is required 246 | * @param string Error associated with the element 247 | * @return array 248 | */ 249 | protected function _elementToArray(&$element, $required, $error) 250 | { 251 | $ret = array( 252 | 'name' => $element->getName(), 253 | 'value' => $element->getValue(), 254 | 'type' => $element->getType(), 255 | 'frozen' => $element->isFrozen(), 256 | 'required' => $required, 257 | 'error' => $error 258 | ); 259 | // render label(s) 260 | $labels = $element->getLabel(); 261 | if (is_array($labels) && $this->_staticLabels) { 262 | foreach($labels as $key => $label) { 263 | $key = is_int($key)? $key + 1: $key; 264 | if (1 === $key) { 265 | $ret['label'] = $label; 266 | } else { 267 | $ret['label_' . $key] = $label; 268 | } 269 | } 270 | } else { 271 | $ret['label'] = $labels; 272 | } 273 | 274 | // set the style for the element 275 | if (isset($this->_elementStyles[$ret['name']])) { 276 | $ret['style'] = $this->_elementStyles[$ret['name']]; 277 | } 278 | if ('group' == $ret['type']) { 279 | $ret['separator'] = $element->_separator; 280 | $ret['elements'] = array(); 281 | } else { 282 | $ret['html'] = $element->toHtml(); 283 | } 284 | return $ret; 285 | } 286 | 287 | 288 | /** 289 | * Stores an array representation of an element in the form array 290 | * 291 | * @param array Array representation of an element 292 | */ 293 | protected function _storeArray($elAry) 294 | { 295 | // where should we put this element... 296 | if (is_array($this->_currentGroup) && ('group' != $elAry['type'])) { 297 | $this->_currentGroup['elements'][] = $elAry; 298 | } elseif (isset($this->_currentSection)) { 299 | $this->_ary['sections'][$this->_currentSection]['elements'][] = $elAry; 300 | } else { 301 | $this->_ary['elements'][] = $elAry; 302 | } 303 | } 304 | 305 | /** 306 | * Sets a style to use for element rendering 307 | * 308 | * @param mixed element name or array ('element name' => 'style name') 309 | * @param string style name if $elementName is not an array 310 | */ 311 | public function setElementStyle($elementName, $styleName = null) 312 | { 313 | if (is_array($elementName)) { 314 | $this->_elementStyles = array_merge($this->_elementStyles, $elementName); 315 | } else { 316 | $this->_elementStyles[$elementName] = $styleName; 317 | } 318 | } 319 | 320 | /** 321 | * @inheritDoc 322 | */ 323 | public function finishForm(&$form) 324 | { 325 | } 326 | 327 | /** 328 | * @inheritDoc 329 | */ 330 | public function renderHtml(&$data) 331 | { 332 | } 333 | } 334 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/Renderer/ArraySmarty.php: -------------------------------------------------------------------------------- 1 | 5 | * @author Bertrand Mansion 6 | * @author Thomas Schulz 7 | * @copyright 2001-2011 The PHP Group 8 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 9 | */ 10 | 11 | /** 12 | * A static renderer for HTML_QuickForm, makes an array of form content 13 | * useful for a Smarty template 14 | * 15 | * Based on old HTML_QuickForm::toArray() code and ITStatic renderer. 16 | * 17 | * The form array structure is the following: 18 | *
 19 |  * Array (
 20 |  *  [frozen]       => whether the complete form is frozen'
 21 |  *  [javascript]   => javascript for client-side validation
 22 |  *  [attributes]   => attributes for  tag
 23 |  *  [hidden]       => html of all hidden elements
 24 |  *  [requirednote] => note about the required elements
 25 |  *  [errors] => Array
 26 |  *      (
 27 |  *          [1st_element_name] => Error for the 1st element
 28 |  *          ...
 29 |  *          [nth_element_name] => Error for the nth element
 30 |  *      )
 31 |  *
 32 |  *  [header] => Array
 33 |  *      (
 34 |  *          [1st_header_name] => Header text for the 1st header
 35 |  *          ...
 36 |  *          [nth_header_name] => Header text for the nth header
 37 |  *      )
 38 |  *
 39 |  *  [1st_element_name] => Array for the 1st element
 40 |  *  ...
 41 |  *  [nth_element_name] => Array for the nth element
 42 |  * 
43 | * 44 | * where an element array has the form: 45 | *
 46 |  *      (
 47 |  *          [name]      => element name
 48 |  *          [value]     => element value,
 49 |  *          [type]      => type of the element
 50 |  *          [frozen]    => whether element is frozen
 51 |  *          [label]     => label for the element
 52 |  *          [required]  => whether element is required
 53 |  * // if element is not a group:
 54 |  *          [html]      => HTML for the element
 55 |  * // if element is a group:
 56 |  *          [separator] => separator for group elements
 57 |  *          [1st_gitem_name] => Array for the 1st element in group
 58 |  *          ...
 59 |  *          [nth_gitem_name] => Array for the nth element in group
 60 |  *      )
 61 |  * )
 62 |  * 
63 | * 64 | * @package HTML_QuickForm 65 | * @author Alexey Borzov 66 | * @author Bertrand Mansion 67 | * @author Thomas Schulz 68 | */ 69 | class HTML_QuickForm_Renderer_ArraySmarty extends HTML_QuickForm_Renderer_Array 70 | { 71 | /** 72 | * The Smarty template engine instance 73 | * @var object 74 | */ 75 | private $_tpl = null; 76 | 77 | /** 78 | * Current element index 79 | * @var integer 80 | */ 81 | private $_elementIdx = 0; 82 | 83 | /** 84 | * The current element index inside a group 85 | * @var integer 86 | */ 87 | private $_groupElementIdx = 0; 88 | 89 | /** 90 | * How to handle the required tag for required fields 91 | * @var string 92 | * @see setRequiredTemplate() 93 | */ 94 | private $_required = ''; 95 | 96 | /** 97 | * How to handle error messages in form validation 98 | * @var string 99 | * @see setErrorTemplate() 100 | */ 101 | private $_error = ''; 102 | 103 | /** 104 | * Constructor 105 | * 106 | * @param Smarty reference to the Smarty template engine instance 107 | * @param bool true: render an array of labels to many labels, $key 0 to 'label' and the oterh to "label_$key" 108 | * @param bool true: collect all hidden elements into string; false: process them as usual form elements 109 | */ 110 | public function __construct(&$tpl, $staticLabels = false, $collectHidden = true) 111 | { 112 | parent::__construct($collectHidden, $staticLabels); 113 | $this->_tpl =& $tpl; 114 | } 115 | 116 | /** 117 | * Called when visiting a form, before processing any form elements 118 | * 119 | * @param HTML_QuickForm a form being visited 120 | */ 121 | public function startForm(&$form) 122 | { 123 | parent::startForm($form); 124 | $this->_elementIdx = 1; 125 | } 126 | 127 | /** 128 | * Called when visiting a header element 129 | * 130 | * @param HTML_QuickForm_header header element being visited 131 | */ 132 | public function renderHeader(&$header) 133 | { 134 | if ($name = $header->getName()) { 135 | $this->_ary['header'][$name] = $header->toHtml(); 136 | } else { 137 | $this->_ary['header'][$this->_sectionCount] = $header->toHtml(); 138 | } 139 | $this->_currentSection = $this->_sectionCount++; 140 | } 141 | 142 | /** 143 | * Called when visiting a group, before processing any group elements 144 | * 145 | * @param HTML_QuickForm_group group being visited 146 | * @param bool Whether a group is required 147 | * @param string An error message associated with a group 148 | */ 149 | public function startGroup(&$group, $required, $error) 150 | { 151 | parent::startGroup($group, $required, $error); 152 | $this->_groupElementIdx = 1; 153 | } 154 | 155 | /** 156 | * Creates an array representing an element containing 157 | * the key for storing this 158 | * 159 | * @access private 160 | * @param HTML_QuickForm_element form element being visited 161 | * @param bool Whether an element is required 162 | * @param string Error associated with the element 163 | * @return array 164 | */ 165 | protected function _elementToArray(&$element, $required, $error) 166 | { 167 | $ret = parent::_elementToArray($element, $required, $error); 168 | 169 | if ('group' == $ret['type']) { 170 | $ret['html'] = $element->toHtml(); 171 | // we don't need the elements, see the array structure 172 | unset($ret['elements']); 173 | } 174 | if (($required || $error) && !empty($this->_required)){ 175 | $this->_renderRequired($ret['label'], $ret['html'], $required, $error); 176 | } 177 | if ($error && !empty($this->_error)) { 178 | $this->_renderError($ret['label'], $ret['html'], $error); 179 | $ret['error'] = $error; 180 | } 181 | // create keys for elements grouped by native group or name 182 | if (strstr($ret['name'], '[') or $this->_currentGroup) { 183 | // Fix for bug #8123: escape backslashes and quotes to prevent errors 184 | // in eval(). The code below seems to handle the case where element 185 | // name has unbalanced square brackets. Dunno whether we really 186 | // need this after the fix for #8123, but I'm wary of making big 187 | // changes to this code. 188 | preg_match('/([^]]*)\\[([^]]*)\\]/', $ret['name'], $matches); 189 | if (isset($matches[1])) { 190 | $sKeysSub = substr_replace($ret['name'], '', 0, strlen($matches[1])); 191 | $sKeysSub = str_replace( 192 | array('\\', '\'', '[' , ']', '[\'\']'), 193 | array('\\\\', '\\\'', '[\'', '\']', '[]' ), 194 | $sKeysSub 195 | ); 196 | $sKeys = '[\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $matches[1]) . '\']' . $sKeysSub; 197 | } else { 198 | $sKeys = '[\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $ret['name']) . '\']'; 199 | } 200 | // special handling for elements in native groups 201 | if ($this->_currentGroup) { 202 | // skip unnamed group items unless radios: no name -> no static access 203 | // identification: have the same key string as the parent group 204 | if ($this->_currentGroup['keys'] == $sKeys and 'radio' != $ret['type']) { 205 | return false; 206 | } 207 | // reduce string of keys by remove leading group keys 208 | if (0 === strpos($sKeys, $this->_currentGroup['keys'])) { 209 | $sKeys = substr_replace($sKeys, '', 0, strlen($this->_currentGroup['keys'])); 210 | } 211 | } 212 | // element without a name 213 | } elseif ($ret['name'] == '') { 214 | $sKeys = '[\'element_' . $this->_elementIdx . '\']'; 215 | // other elements 216 | } else { 217 | $sKeys = '[\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $ret['name']) . '\']'; 218 | } 219 | // for radios: add extra key from value 220 | if ('radio' == $ret['type'] and substr($sKeys, -2) != '[]') { 221 | $sKeys .= '[\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $ret['value']) . '\']'; 222 | } 223 | $this->_elementIdx++; 224 | $ret['keys'] = $sKeys; 225 | return $ret; 226 | } 227 | 228 | /** 229 | * Stores an array representation of an element in the form array 230 | * 231 | * @access private 232 | * @param array Array representation of an element 233 | */ 234 | protected function _storeArray($elAry) 235 | { 236 | if ($elAry) { 237 | $sKeys = $elAry['keys']; 238 | unset($elAry['keys']); 239 | // where should we put this element... 240 | if (is_array($this->_currentGroup) && ('group' != $elAry['type'])) { 241 | $toEval = '$this->_currentGroup' . $sKeys . ' = $elAry;'; 242 | } else { 243 | $toEval = '$this->_ary' . $sKeys . ' = $elAry;'; 244 | } 245 | eval($toEval); 246 | } 247 | return; 248 | } 249 | 250 | /** 251 | * Called when an element is required 252 | * 253 | * This method will add the required tag to the element label and/or the element html 254 | * such as defined with the method setRequiredTemplate. 255 | * 256 | * @param string The element label 257 | * @param string The element html rendering 258 | * @param boolean The element required 259 | * @param string The element error 260 | * @see setRequiredTemplate() 261 | * @access private 262 | */ 263 | private function _renderRequired(&$label, &$html, &$required, &$error) 264 | { 265 | $this->_tpl->assign(array( 266 | 'label' => $label, 267 | 'html' => $html, 268 | 'required' => $required, 269 | 'error' => $error 270 | )); 271 | if (!empty($label) && strpos($this->_required, $this->_tpl->left_delimiter . '$label') !== false) { 272 | $label = $this->_tplFetch($this->_required); 273 | } 274 | if (!empty($html) && strpos($this->_required, $this->_tpl->left_delimiter . '$html') !== false) { 275 | $html = $this->_tplFetch($this->_required); 276 | } 277 | $this->_tpl->clear_assign(array('label', 'html', 'required')); 278 | } 279 | 280 | /** 281 | * Called when an element has a validation error 282 | * 283 | * This method will add the error message to the element label or the element html 284 | * such as defined with the method setErrorTemplate. If the error placeholder is not found 285 | * in the template, the error will be displayed in the form error block. 286 | * 287 | * @param string The element label 288 | * @param string The element html rendering 289 | * @param string The element error 290 | * @see setErrorTemplate() 291 | * @access private 292 | */ 293 | private function _renderError(&$label, &$html, &$error) 294 | { 295 | $this->_tpl->assign(array('label' => '', 'html' => '', 'error' => $error)); 296 | $error = $this->_tplFetch($this->_error); 297 | $this->_tpl->assign(array('label' => $label, 'html' => $html)); 298 | 299 | if (!empty($label) && strpos($this->_error, $this->_tpl->left_delimiter . '$label') !== false) { 300 | $label = $this->_tplFetch($this->_error); 301 | } elseif (!empty($html) && strpos($this->_error, $this->_tpl->left_delimiter . '$html') !== false) { 302 | $html = $this->_tplFetch($this->_error); 303 | } 304 | $this->_tpl->clear_assign(array('label', 'html', 'error')); 305 | } 306 | 307 | /** 308 | * Process an template sourced in a string with Smarty 309 | * 310 | * Smarty has no core function to render a template given as a string. 311 | * So we use the smarty eval plugin function to do this. 312 | * 313 | * @param string The template source 314 | * @access private 315 | */ 316 | private function _tplFetch($tplSource) 317 | { 318 | if (!function_exists('smarty_function_eval')) { 319 | require SMARTY_DIR . '/plugins/function.eval.php'; 320 | } 321 | return smarty_function_eval(array('var' => $tplSource), $this->_tpl); 322 | } 323 | 324 | /** 325 | * Sets the way required elements are rendered 326 | * 327 | * You can use {$label} or {$html} placeholders to let the renderer know where 328 | * where the element label or the element html are positionned according to the 329 | * required tag. They will be replaced accordingly with the right value. You 330 | * can use the full smarty syntax here, especially a custom modifier for I18N. 331 | * For example: 332 | * {if $required}*{/if}{$label|translate} 333 | * will put a red star in front of the label if the element is required and 334 | * translate the label. 335 | * 336 | * 337 | * @param string The required element template 338 | */ 339 | public function setRequiredTemplate($template) 340 | { 341 | $this->_required = $template; 342 | } 343 | 344 | /** 345 | * Sets the way elements with validation errors are rendered 346 | * 347 | * You can use {$label} or {$html} placeholders to let the renderer know where 348 | * where the element label or the element html are positionned according to the 349 | * error message. They will be replaced accordingly with the right value. 350 | * The error message will replace the {$error} placeholder. 351 | * For example: 352 | * {if $error}{$error}{/if}
{$html} 353 | * will put the error message in red on top of the element html. 354 | * 355 | * If you want all error messages to be output in the main error block, use 356 | * the {$form.errors} part of the rendered array that collects all raw error 357 | * messages. 358 | * 359 | * If you want to place all error messages manually, do not specify {$html} 360 | * nor {$label}. 361 | * 362 | * Groups can have special layouts. With this kind of groups, you have to 363 | * place the formated error message manually. In this case, use {$form.group.error} 364 | * where you want the formated error message to appear in the form. 365 | * 366 | * @param string The element error template 367 | */ 368 | public function setErrorTemplate($template) 369 | { 370 | $this->_error = $template; 371 | } 372 | } 373 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/Renderer/Default.php: -------------------------------------------------------------------------------- 1 | 5 | * @author Adam Daniel 6 | * @author Bertrand Mansion 7 | * @copyright 2001-2011 The PHP Group 8 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 9 | */ 10 | 11 | /** 12 | * A concrete renderer for HTML_QuickForm, based on QuickForm 2.x built-in one 13 | * 14 | * @package HTML_QuickForm 15 | * @author Alexey Borzov 16 | * @author Adam Daniel 17 | * @author Bertrand Mansion 18 | */ 19 | class HTML_QuickForm_Renderer_Default extends HTML_QuickForm_Renderer 20 | { 21 | /** 22 | * The HTML of the form 23 | * @var string 24 | * @access private 25 | */ 26 | var $_html; 27 | 28 | /** 29 | * Header Template string 30 | * @var string 31 | * @access private 32 | */ 33 | var $_headerTemplate = 34 | "\n\t\n\t\t{header}\n\t"; 35 | 36 | /** 37 | * Element template string 38 | * @var string 39 | * @access private 40 | */ 41 | var $_elementTemplate = 42 | "\n\t\n\t\t*{label}\n\t\t{error}
\t{element}\n\t"; 43 | 44 | /** 45 | * Form template string 46 | * @var string 47 | * @access private 48 | */ 49 | var $_formTemplate = 50 | "\n\n
\n{hidden}\n{content}\n
\n
\n"; 51 | 52 | /** 53 | * Required Note template string 54 | * @var string 55 | * @access private 56 | */ 57 | var $_requiredNoteTemplate = 58 | "\n\t\n\t\t\n\t{requiredNote}\n\t"; 59 | 60 | /** 61 | * Array containing the templates for customised elements 62 | * @var array 63 | * @access private 64 | */ 65 | var $_templates = array(); 66 | 67 | /** 68 | * Array containing the templates for group wraps. 69 | * 70 | * These templates are wrapped around group elements and groups' own 71 | * templates wrap around them. This is set by setGroupTemplate(). 72 | * 73 | * @var array 74 | * @access private 75 | */ 76 | var $_groupWraps = array(); 77 | 78 | /** 79 | * Array containing the templates for elements within groups 80 | * @var array 81 | * @access private 82 | */ 83 | var $_groupTemplates = array(); 84 | 85 | /** 86 | * True if we are inside a group 87 | * @var bool 88 | * @access private 89 | */ 90 | var $_inGroup = false; 91 | 92 | /** 93 | * Array with HTML generated for group elements 94 | * @var array 95 | * @access private 96 | */ 97 | var $_groupElements = array(); 98 | 99 | /** 100 | * Template for an element inside a group 101 | * @var string 102 | * @access private 103 | */ 104 | var $_groupElementTemplate = ''; 105 | 106 | /** 107 | * HTML that wraps around the group elements 108 | * @var string 109 | * @access private 110 | */ 111 | var $_groupWrap = ''; 112 | 113 | /** 114 | * HTML for the current group 115 | * @var string 116 | * @access private 117 | */ 118 | var $_groupTemplate = ''; 119 | 120 | /** 121 | * Collected HTML of the hidden fields 122 | * @var string 123 | * @access private 124 | */ 125 | var $_hiddenHtml = ''; 126 | 127 | /** 128 | * returns the HTML generated for the form 129 | * 130 | * @return string 131 | */ 132 | public function toHtml() 133 | { 134 | // _hiddenHtml is cleared in finishForm(), so this only matters when 135 | // finishForm() was not called (e.g. group::toHtml(), bug #3511) 136 | return $this->_hiddenHtml . $this->_html; 137 | } 138 | 139 | /** 140 | * Called when visiting a form, before processing any form elements 141 | * 142 | * @param HTML_QuickForm form object being visited 143 | */ 144 | public function startForm(&$form) 145 | { 146 | $this->_html = ''; 147 | $this->_hiddenHtml = ''; 148 | } 149 | 150 | /** 151 | * Called when visiting a form, after processing all form elements 152 | * Adds required note, form attributes, validation javascript and form content. 153 | * 154 | * @param HTML_QuickForm form object being visited 155 | */ 156 | public function finishForm(&$form) 157 | { 158 | // add a required note, if one is needed 159 | if (!empty($form->_required) && !$form->_freezeAll) { 160 | $this->_html .= str_replace('{requiredNote}', $form->getRequiredNote(), $this->_requiredNoteTemplate); 161 | } 162 | // add form attributes and content 163 | $html = str_replace('{attributes}', $form->getAttributes(true), $this->_formTemplate); 164 | if (strpos($this->_formTemplate, '{hidden}')) { 165 | $html = str_replace('{hidden}', $this->_hiddenHtml, $html); 166 | } else { 167 | $this->_html .= $this->_hiddenHtml; 168 | } 169 | $this->_hiddenHtml = ''; 170 | $this->_html = str_replace('{content}', $this->_html, $html); 171 | // add a validation script 172 | if ('' != ($script = $form->getValidationScript())) { 173 | $this->_html = $script . "\n" . $this->_html; 174 | } 175 | } 176 | 177 | /** 178 | * Called when visiting a header element 179 | * 180 | * @param HTML_QuickForm_header header element being visited 181 | */ 182 | public function renderHeader(&$header) 183 | { 184 | $name = $header->getName(); 185 | if (!empty($name) && isset($this->_templates[$name])) { 186 | $this->_html .= str_replace('{header}', $header->toHtml(), $this->_templates[$name]); 187 | } else { 188 | $this->_html .= str_replace('{header}', $header->toHtml(), $this->_headerTemplate); 189 | } 190 | } 191 | 192 | /** 193 | * Helper method for renderElement 194 | * 195 | * @param string Element name 196 | * @param mixed Element label (if using an array of labels, you should set the appropriate template) 197 | * @param bool Whether an element is required 198 | * @param string Error message associated with the element 199 | * @access private 200 | * @see renderElement() 201 | * @return string Html for element 202 | */ 203 | function _prepareTemplate($name, $label, $required, $error) 204 | { 205 | if (is_array($label)) { 206 | $nameLabel = array_shift($label); 207 | } else { 208 | $nameLabel = $label; 209 | } 210 | if (isset($this->_templates[$name])) { 211 | $html = str_replace('{label}', $nameLabel, $this->_templates[$name]); 212 | } else { 213 | $html = str_replace('{label}', $nameLabel, $this->_elementTemplate); 214 | } 215 | if ($required) { 216 | $html = str_replace('', '', $html); 217 | $html = str_replace('', '', $html); 218 | } else { 219 | $html = preg_replace("/([ \t\n\r]*)?.*([ \t\n\r]*)?/isU", '', $html); 220 | } 221 | if (isset($error)) { 222 | $html = str_replace('{error}', $error, $html); 223 | $html = str_replace('', '', $html); 224 | $html = str_replace('', '', $html); 225 | } else { 226 | $html = preg_replace("/([ \t\n\r]*)?.*([ \t\n\r]*)?/isU", '', $html); 227 | } 228 | if (is_array($label)) { 229 | foreach($label as $key => $text) { 230 | $key = is_int($key)? $key + 2: $key; 231 | $html = str_replace("{label_{$key}}", $text, $html); 232 | $html = str_replace("", '', $html); 233 | $html = str_replace("", '', $html); 234 | } 235 | } 236 | if (strpos($html, '{label_')) { 237 | $html = preg_replace('/\s*.*\s*/is', '', $html); 238 | } 239 | return $html; 240 | } 241 | 242 | /** 243 | * Renders an element Html 244 | * Called when visiting an element 245 | * 246 | * @param HTML_QuickForm_element form element being visited 247 | * @param bool Whether an element is required 248 | * @param string An error message associated with an element 249 | */ 250 | public function renderElement(&$element, $required, $error) 251 | { 252 | if (!$this->_inGroup) { 253 | $html = $this->_prepareTemplate($element->getName(), $element->getLabel(), $required, $error); 254 | $this->_html .= str_replace('{element}', $element->toHtml(), $html); 255 | 256 | } elseif (!empty($this->_groupElementTemplate)) { 257 | $html = str_replace('{label}', $element->getLabel(), $this->_groupElementTemplate); 258 | if ($required) { 259 | $html = str_replace('', '', $html); 260 | $html = str_replace('', '', $html); 261 | } else { 262 | $html = preg_replace("/([ \t\n\r]*)?.*([ \t\n\r]*)?/isU", '', $html); 263 | } 264 | $this->_groupElements[] = str_replace('{element}', $element->toHtml(), $html); 265 | 266 | } else { 267 | $this->_groupElements[] = $element->toHtml(); 268 | } 269 | } 270 | 271 | /** 272 | * @inheritDoc 273 | */ 274 | public function renderHidden(&$element, $required, $error) 275 | { 276 | $this->_hiddenHtml .= $element->toHtml() . "\n"; 277 | } 278 | 279 | /** 280 | * Called when visiting a raw HTML/text pseudo-element 281 | * 282 | * @param HTML_QuickForm_html element being visited 283 | */ 284 | public function renderHtml(&$data) 285 | { 286 | $this->_html .= $data->toHtml(); 287 | } 288 | 289 | /** 290 | * Called when visiting a group, before processing any group elements 291 | * 292 | * @param HTML_QuickForm_group group being visited 293 | * @param bool Whether a group is required 294 | * @param string An error message associated with a group 295 | */ 296 | public function startGroup(&$group, $required, $error) 297 | { 298 | $name = $group->getName(); 299 | $this->_groupTemplate = $this->_prepareTemplate($name, $group->getLabel(), $required, $error); 300 | $this->_groupElementTemplate = empty($this->_groupTemplates[$name])? '': $this->_groupTemplates[$name]; 301 | $this->_groupWrap = empty($this->_groupWraps[$name])? '': $this->_groupWraps[$name]; 302 | $this->_groupElements = array(); 303 | $this->_inGroup = true; 304 | } 305 | 306 | /** 307 | * Called when visiting a group, after processing all group elements 308 | * 309 | * @param HTML_QuickForm_group group being visited 310 | */ 311 | public function finishGroup(&$group) 312 | { 313 | $separator = $group->_separator; 314 | if (is_array($separator)) { 315 | $count = count($separator); 316 | $html = ''; 317 | for ($i = 0; $i < count($this->_groupElements); $i++) { 318 | $html .= (0 == $i? '': $separator[($i - 1) % $count]) . $this->_groupElements[$i]; 319 | } 320 | } else { 321 | if (is_null($separator)) { 322 | $separator = ' '; 323 | } 324 | $html = implode((string)$separator, $this->_groupElements); 325 | } 326 | if (!empty($this->_groupWrap)) { 327 | $html = str_replace('{content}', $html, $this->_groupWrap); 328 | } 329 | $this->_html .= str_replace('{element}', $html, $this->_groupTemplate); 330 | $this->_inGroup = false; 331 | } 332 | 333 | /** 334 | * Sets element template 335 | * 336 | * @param string The HTML surrounding an element 337 | * @param string (optional) Name of the element to apply template for 338 | */ 339 | public function setElementTemplate($html, $element = null) 340 | { 341 | if (is_null($element)) { 342 | $this->_elementTemplate = $html; 343 | } else { 344 | $this->_templates[$element] = $html; 345 | } 346 | } 347 | 348 | /** 349 | * Sets template for a group wrapper 350 | * 351 | * This template is contained within a group-as-element template 352 | * set via setTemplate() and contains group's element templates, set 353 | * via setGroupElementTemplate() 354 | * 355 | * @param string The HTML surrounding group elements 356 | * @param string Name of the group to apply template for 357 | */ 358 | public function setGroupTemplate($html, $group) 359 | { 360 | $this->_groupWraps[$group] = $html; 361 | } 362 | 363 | /** 364 | * Sets element template for elements within a group 365 | * 366 | * @param string The HTML surrounding an element 367 | * @param string Name of the group to apply template for 368 | */ 369 | public function setGroupElementTemplate($html, $group) 370 | { 371 | $this->_groupTemplates[$group] = $html; 372 | } 373 | 374 | /** 375 | * Sets header template 376 | * 377 | * @param string The HTML surrounding the header 378 | */ 379 | public function setHeaderTemplate($html) 380 | { 381 | $this->_headerTemplate = $html; 382 | } 383 | 384 | /** 385 | * Sets form template 386 | * 387 | * @param string The HTML surrounding the form tags 388 | */ 389 | public function setFormTemplate($html) 390 | { 391 | $this->_formTemplate = $html; 392 | } 393 | 394 | /** 395 | * Sets the note indicating required fields template 396 | * 397 | * @param string The HTML surrounding the required note 398 | */ 399 | public function setRequiredNoteTemplate($html) 400 | { 401 | $this->_requiredNoteTemplate = $html; 402 | } 403 | 404 | /** 405 | * Clears all the HTML out of the templates that surround notes, elements, etc. 406 | * Useful when you want to use addData() to create a completely custom form look 407 | */ 408 | public function clearAllTemplates() 409 | { 410 | $this->setElementTemplate('{element}'); 411 | $this->setFormTemplate("\n\t{content}\n\t\n"); 412 | $this->setRequiredNoteTemplate(''); 413 | $this->_templates = array(); 414 | } 415 | } 416 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/Renderer/ITDynamic.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2001-2011 The PHP Group 6 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 7 | */ 8 | 9 | /** 10 | * A concrete renderer for HTML_QuickForm, using Integrated Templates. 11 | * 12 | * This is a "dynamic" renderer, which means that concrete form look 13 | * is defined at runtime. This also means that you can define 14 | * one template file for all your forms. That template 15 | * should contain a block for every element 'look' appearing in your 16 | * forms and also some special blocks (consult the examples). If a 17 | * special block is not set for an element, the renderer falls back to 18 | * a default one. 19 | * 20 | * @package HTML_QuickForm 21 | * @author Alexey Borzov 22 | */ 23 | class HTML_QuickForm_Renderer_ITDynamic extends HTML_QuickForm_Renderer 24 | { 25 | /**#@+ 26 | * @access private 27 | */ 28 | /** 29 | * A template class (HTML_Template_ITX or HTML_Template_Sigma) instance 30 | * @var HTML_Template_ITX|HTML_Template_Sigma 31 | */ 32 | var $_tpl = null; 33 | 34 | /** 35 | * The errors that were not shown near concrete fields go here 36 | * @var array 37 | */ 38 | var $_errors = array(); 39 | 40 | /** 41 | * Show the block with required note? 42 | * @var bool 43 | */ 44 | var $_showRequired = false; 45 | 46 | /** 47 | * A separator for group elements 48 | * @var mixed 49 | */ 50 | var $_groupSeparator = null; 51 | 52 | /** 53 | * The current element index inside a group 54 | * @var integer 55 | */ 56 | var $_groupElementIdx = 0; 57 | 58 | /** 59 | * Blocks to use for different elements 60 | * @var array 61 | */ 62 | var $_elementBlocks = array(); 63 | 64 | /** 65 | * Block to use for headers 66 | * @var string 67 | */ 68 | var $_headerBlock = null; 69 | /**#@-*/ 70 | 71 | 72 | /** 73 | * Constructor 74 | * 75 | * @param HTML_Template_ITX|HTML_Template_Sigma Template object to use 76 | */ 77 | public function __construct(&$tpl) 78 | { 79 | $this->_tpl =& $tpl; 80 | $this->_tpl->setCurrentBlock('qf_main_loop'); 81 | } 82 | 83 | public function startForm(&$form) 84 | { 85 | } 86 | 87 | public function renderHtml(&$data) 88 | { 89 | } 90 | 91 | function finishForm(&$form) 92 | { 93 | // display errors above form 94 | if (!empty($this->_errors) && $this->_tpl->blockExists('qf_error_loop')) { 95 | foreach ($this->_errors as $error) { 96 | $this->_tpl->setVariable('qf_error', $error); 97 | $this->_tpl->parse('qf_error_loop'); 98 | } 99 | } 100 | // show required note 101 | if ($this->_showRequired) { 102 | $this->_tpl->setVariable('qf_required_note', $form->getRequiredNote()); 103 | } 104 | // assign form attributes 105 | $this->_tpl->setVariable('qf_attributes', $form->getAttributes(true)); 106 | // assign javascript validation rules 107 | $this->_tpl->setVariable('qf_javascript', $form->getValidationScript()); 108 | } 109 | 110 | function renderHeader(&$header) 111 | { 112 | $blockName = $this->_matchBlock($header); 113 | if ('qf_header' == $blockName && isset($this->_headerBlock)) { 114 | $blockName = $this->_headerBlock; 115 | } 116 | $this->_tpl->setVariable('qf_header', $header->toHtml()); 117 | $this->_tpl->parse($blockName); 118 | $this->_tpl->parse('qf_main_loop'); 119 | } 120 | 121 | 122 | function renderElement(&$element, $required, $error) 123 | { 124 | $blockName = $this->_matchBlock($element); 125 | // are we inside a group? 126 | if ('qf_main_loop' != $this->_tpl->currentBlock) { 127 | if (0 != $this->_groupElementIdx && $this->_tpl->placeholderExists('qf_separator', $blockName)) { 128 | if (is_array($this->_groupSeparator)) { 129 | $this->_tpl->setVariable('qf_separator', $this->_groupSeparator[($this->_groupElementIdx - 1) % count($this->_groupSeparator)]); 130 | } else { 131 | $this->_tpl->setVariable('qf_separator', (string)$this->_groupSeparator); 132 | } 133 | } 134 | $this->_groupElementIdx++; 135 | 136 | } elseif(!empty($error)) { 137 | // show the error message or keep it for later use 138 | if ($this->_tpl->blockExists($blockName . '_error')) { 139 | $this->_tpl->setVariable('qf_error', $error); 140 | } else { 141 | $this->_errors[] = $error; 142 | } 143 | } 144 | // show an '*' near the required element 145 | if ($required) { 146 | $this->_showRequired = true; 147 | if ($this->_tpl->blockExists($blockName . '_required')) { 148 | $this->_tpl->touchBlock($blockName . '_required'); 149 | } 150 | } 151 | // Prepare multiple labels 152 | $labels = $element->getLabel(); 153 | if (is_array($labels)) { 154 | $mainLabel = array_shift($labels); 155 | } else { 156 | $mainLabel = $labels; 157 | } 158 | // render the element itself with its main label 159 | $this->_tpl->setVariable('qf_element', $element->toHtml()); 160 | if ($this->_tpl->placeholderExists('qf_label', $blockName)) { 161 | $this->_tpl->setVariable('qf_label', $mainLabel); 162 | } 163 | // render extra labels, if any 164 | if (is_array($labels)) { 165 | foreach($labels as $key => $label) { 166 | $key = is_int($key)? $key + 2: $key; 167 | if ($this->_tpl->blockExists($blockName . '_label_' . $key)) { 168 | $this->_tpl->setVariable('qf_label_' . $key, $label); 169 | } 170 | } 171 | } 172 | $this->_tpl->parse($blockName); 173 | $this->_tpl->parseCurrentBlock(); 174 | } 175 | 176 | /** 177 | * @inheritDoc 178 | */ 179 | function renderHidden(&$element, $required, $error) 180 | { 181 | $this->_tpl->setVariable('qf_hidden', $element->toHtml()); 182 | $this->_tpl->parse('qf_hidden_loop'); 183 | } 184 | 185 | 186 | function startGroup(&$group, $required, $error) 187 | { 188 | $blockName = $this->_matchBlock($group); 189 | $this->_tpl->setCurrentBlock($blockName . '_loop'); 190 | $this->_groupElementIdx = 0; 191 | $this->_groupSeparator = is_null($group->_separator)? ' ': $group->_separator; 192 | // show an '*' near the required element 193 | if ($required) { 194 | $this->_showRequired = true; 195 | if ($this->_tpl->blockExists($blockName . '_required')) { 196 | $this->_tpl->touchBlock($blockName . '_required'); 197 | } 198 | } 199 | // show the error message or keep it for later use 200 | if (!empty($error)) { 201 | if ($this->_tpl->blockExists($blockName . '_error')) { 202 | $this->_tpl->setVariable('qf_error', $error); 203 | } else { 204 | $this->_errors[] = $error; 205 | } 206 | } 207 | $this->_tpl->setVariable('qf_group_label', $group->getLabel()); 208 | } 209 | 210 | 211 | function finishGroup(&$group) 212 | { 213 | $this->_tpl->parse($this->_matchBlock($group)); 214 | $this->_tpl->setCurrentBlock('qf_main_loop'); 215 | $this->_tpl->parseCurrentBlock(); 216 | } 217 | 218 | 219 | /** 220 | * Returns the name of a block to use for element rendering 221 | * 222 | * If a name was not explicitly set via setElementBlock(), it tries 223 | * the names '{prefix}_{element type}' and '{prefix}_{element}', where 224 | * prefix is either 'qf' or the name of the current group's block 225 | * 226 | * @param HTML_QuickForm_element form element being rendered 227 | * @access private 228 | * @return string block name 229 | */ 230 | function _matchBlock(&$element) 231 | { 232 | $name = $element->getName(); 233 | $type = $element->getType(); 234 | if (isset($this->_elementBlocks[$name]) && $this->_tpl->blockExists($this->_elementBlocks[$name])) { 235 | if (('group' == $type) || ($this->_elementBlocks[$name] . '_loop' != $this->_tpl->currentBlock)) { 236 | return $this->_elementBlocks[$name]; 237 | } 238 | } 239 | if ('group' != $type && 'qf_main_loop' != $this->_tpl->currentBlock) { 240 | $prefix = substr($this->_tpl->currentBlock, 0, -5); // omit '_loop' postfix 241 | } else { 242 | $prefix = 'qf'; 243 | } 244 | if ($this->_tpl->blockExists($prefix . '_' . $type)) { 245 | return $prefix . '_' . $type; 246 | } elseif ($this->_tpl->blockExists($prefix . '_' . $name)) { 247 | return $prefix . '_' . $name; 248 | } else { 249 | return $prefix . '_element'; 250 | } 251 | } 252 | 253 | /** 254 | * Sets the block to use for element rendering 255 | * 256 | * @param mixed element name or array ('element name' => 'block name') 257 | * @param string block name if $elementName is not an array 258 | */ 259 | public function setElementBlock($elementName, $blockName = null) 260 | { 261 | if (is_array($elementName)) { 262 | $this->_elementBlocks = array_merge($this->_elementBlocks, $elementName); 263 | } else { 264 | $this->_elementBlocks[$elementName] = $blockName; 265 | } 266 | } 267 | 268 | /** 269 | * Sets the name of a block to use for header rendering 270 | * 271 | * @param string block name 272 | */ 273 | public function setHeaderBlock($blockName) 274 | { 275 | $this->_headerBlock = $blockName; 276 | } 277 | } 278 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/Renderer/Object.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2001-2011 The PHP Group 6 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 7 | */ 8 | 9 | /** 10 | * A concrete renderer for HTML_QuickForm, makes an object from form contents 11 | * 12 | * Based on HTML_Quickform_Renderer_Array code 13 | * 14 | * @package HTML_QuickForm 15 | * @author Ron McClain 16 | */ 17 | class HTML_QuickForm_Renderer_Object extends HTML_QuickForm_Renderer 18 | { 19 | /**#@+ 20 | * @access private 21 | */ 22 | /** 23 | * The object being generated 24 | * @var QuickformForm 25 | */ 26 | var $_obj= null; 27 | 28 | /** 29 | * Number of sections in the form (i.e. number of headers in it) 30 | * @var integer $_sectionCount 31 | */ 32 | var $_sectionCount; 33 | 34 | /** 35 | * Current section number 36 | * @var integer $_currentSection 37 | */ 38 | var $_currentSection; 39 | 40 | /** 41 | * Object representing current group 42 | * @var object $_currentGroup 43 | */ 44 | var $_currentGroup = null; 45 | 46 | /** 47 | * Class of Element Objects 48 | * @var object $_elementType 49 | */ 50 | var $_elementType = 'QuickFormElement'; 51 | 52 | /** 53 | * Additional style information for different elements 54 | * @var array $_elementStyles 55 | */ 56 | var $_elementStyles = array(); 57 | 58 | /** 59 | * true: collect all hidden elements into string; false: process them as usual form elements 60 | * @var bool $_collectHidden 61 | */ 62 | var $_collectHidden = false; 63 | /**#@-*/ 64 | 65 | 66 | /** 67 | * Constructor 68 | * 69 | * @param bool true: collect all hidden elements 70 | */ 71 | public function __construct($collecthidden = false) 72 | { 73 | $this->_collectHidden = $collecthidden; 74 | $this->_obj = new QuickformForm; 75 | } 76 | 77 | /** 78 | * Return the rendered Object 79 | */ 80 | public function toObject() 81 | { 82 | return $this->_obj; 83 | } 84 | 85 | /** 86 | * Set the class of the form elements. Defaults to QuickformElement. 87 | * 88 | * @param string Name of element class 89 | */ 90 | public function setElementType($type) 91 | { 92 | $this->_elementType = $type; 93 | } 94 | 95 | function startForm(&$form) 96 | { 97 | $this->_obj->frozen = $form->isFrozen(); 98 | $this->_obj->javascript = $form->getValidationScript(); 99 | $this->_obj->attributes = $form->getAttributes(true); 100 | $this->_obj->requirednote = $form->getRequiredNote(); 101 | $this->_obj->errors = new StdClass; 102 | 103 | if($this->_collectHidden) { 104 | $this->_obj->hidden = ''; 105 | } 106 | $this->_elementIdx = 1; 107 | $this->_currentSection = null; 108 | $this->_sectionCount = 0; 109 | } 110 | 111 | public function renderHtml(&$data) 112 | { 113 | } 114 | 115 | public function finishForm(&$form) 116 | { 117 | } 118 | 119 | function renderHeader(&$header) 120 | { 121 | $hobj = new StdClass; 122 | $hobj->header = $header->toHtml(); 123 | $this->_obj->sections[$this->_sectionCount] = $hobj; 124 | $this->_currentSection = $this->_sectionCount++; 125 | } 126 | 127 | function renderElement(&$element, $required, $error) 128 | { 129 | $elObj = $this->_elementToObject($element, $required, $error); 130 | if(!empty($error)) { 131 | $name = $elObj->name; 132 | $this->_obj->errors->$name = $error; 133 | } 134 | $this->_storeObject($elObj); 135 | } 136 | 137 | /** 138 | * @inheritDoc 139 | */ 140 | function renderHidden(&$element, $required, $error) 141 | { 142 | if($this->_collectHidden) { 143 | $this->_obj->hidden .= $element->toHtml() . "\n"; 144 | } else { 145 | $this->renderElement($element, $required, $error); 146 | } 147 | } 148 | 149 | function startGroup(&$group, $required, $error) 150 | { 151 | $this->_currentGroup = $this->_elementToObject($group, $required, $error); 152 | if(!empty($error)) { 153 | $name = $this->_currentGroup->name; 154 | $this->_obj->errors->$name = $error; 155 | } 156 | } 157 | 158 | function finishGroup(&$group) 159 | { 160 | $this->_storeObject($this->_currentGroup); 161 | $this->_currentGroup = null; 162 | } 163 | 164 | /** 165 | * Creates an object representing an element 166 | * 167 | * @access private 168 | * @param HTML_QuickForm_element form element being rendered 169 | * @param required bool Whether an element is required 170 | * @param error string Error associated with the element 171 | * @return object 172 | */ 173 | function _elementToObject(&$element, $required, $error) 174 | { 175 | if($this->_elementType) { 176 | $ret = new $this->_elementType; 177 | } 178 | $ret->name = $element->getName(); 179 | $ret->value = $element->getValue(); 180 | $ret->type = $element->getType(); 181 | $ret->frozen = $element->isFrozen(); 182 | $labels = $element->getLabel(); 183 | if (is_array($labels)) { 184 | $ret->label = array_shift($labels); 185 | foreach ($labels as $key => $label) { 186 | $key = is_int($key)? $key + 2: $key; 187 | $ret->{'label_' . $key} = $label; 188 | } 189 | } else { 190 | $ret->label = $labels; 191 | } 192 | $ret->required = $required; 193 | $ret->error = $error; 194 | 195 | if(isset($this->_elementStyles[$ret->name])) { 196 | $ret->style = $this->_elementStyles[$ret->name]; 197 | $ret->styleTemplate = "styles/". $ret->style .".html"; 198 | } 199 | if($ret->type == 'group') { 200 | $ret->separator = $element->_separator; 201 | $ret->elements = array(); 202 | } else { 203 | $ret->html = $element->toHtml(); 204 | } 205 | return $ret; 206 | } 207 | 208 | /** 209 | * Stores an object representation of an element in the form array 210 | * 211 | * @access private 212 | * @param QuickformElement Object representation of an element 213 | */ 214 | function _storeObject($elObj) 215 | { 216 | $name = $elObj->name; 217 | if(is_object($this->_currentGroup) && $elObj->type != 'group') { 218 | $this->_currentGroup->elements[] = $elObj; 219 | } elseif (isset($this->_currentSection)) { 220 | $this->_obj->sections[$this->_currentSection]->elements[] = $elObj; 221 | } else { 222 | $this->_obj->elements[] = $elObj; 223 | } 224 | } 225 | 226 | function setElementStyle($elementName, $styleName = null) 227 | { 228 | if(is_array($elementName)) { 229 | $this->_elementStyles = array_merge($this->_elementStyles, $elementName); 230 | } else { 231 | $this->_elementStyles[$elementName] = $styleName; 232 | } 233 | } 234 | 235 | } 236 | 237 | /** 238 | * Convenience class for the form object passed to outputObject() 239 | * 240 | * Eg. 241 | *
242 |  * {form.outputJavaScript():h}
243 |  * {form.outputHeader():h}
244 |  *   
245 |  *     
246 |  *       
247 |  *     
248 |  *   
{form.name.label:h}{form.name.html:h}
249 | * 250 | *
251 | * 252 | * @package HTML_QuickForm 253 | * @author Ron McClain 254 | */ 255 | class QuickformForm 256 | { 257 | /** 258 | * Whether the form has been frozen 259 | * @var boolean $frozen 260 | */ 261 | var $frozen; 262 | 263 | /** 264 | * Javascript for client-side validation 265 | * @var string $javascript 266 | */ 267 | var $javascript; 268 | 269 | /** 270 | * Attributes for form tag 271 | * @var string $attributes 272 | */ 273 | var $attributes; 274 | 275 | /** 276 | * Note about required elements 277 | * @var string $requirednote 278 | */ 279 | var $requirednote; 280 | 281 | /** 282 | * Collected html of all hidden variables 283 | * @var string $hidden 284 | */ 285 | var $hidden; 286 | 287 | /** 288 | * Set if there were validation errors. 289 | * StdClass object with element names for keys and their 290 | * error messages as values 291 | * @var object $errors 292 | */ 293 | var $errors; 294 | 295 | /** 296 | * Array of QuickformElementObject elements. If there are headers in the form 297 | * this will be empty and the elements will be in the 298 | * separate sections 299 | * @var array $elements 300 | */ 301 | var $elements; 302 | 303 | /** 304 | * Array of sections contained in the document 305 | * @var array $sections 306 | */ 307 | var $sections; 308 | 309 | /** 310 | * Output <form> header 311 | * {form.outputHeader():h} 312 | * @return string <form attributes> 313 | */ 314 | function outputHeader() 315 | { 316 | return "
attributes . ">\n"; 317 | } 318 | 319 | /** 320 | * Output form javascript 321 | * {form.outputJavaScript():h} 322 | * @return string Javascript 323 | */ 324 | function outputJavaScript() 325 | { 326 | return $this->javascript; 327 | } 328 | } 329 | 330 | 331 | /** 332 | * Convenience class describing a form element. 333 | * 334 | * The properties defined here will be available from 335 | * your flexy templates by referencing 336 | * {form.zip.label:h}, {form.zip.html:h}, etc. 337 | * 338 | * @package HTML_QuickForm 339 | * @author Ron McClain 340 | */ 341 | class QuickformElement 342 | { 343 | /** 344 | * Element name 345 | * @var string $name 346 | */ 347 | var $name; 348 | 349 | /** 350 | * Element value 351 | * @var mixed $value 352 | */ 353 | var $value; 354 | 355 | /** 356 | * Type of element 357 | * @var string $type 358 | */ 359 | var $type; 360 | 361 | /** 362 | * Whether the element is frozen 363 | * @var boolean $frozen 364 | */ 365 | var $frozen; 366 | 367 | /** 368 | * Label for the element 369 | * @var string $label 370 | */ 371 | var $label; 372 | 373 | /** 374 | * Whether element is required 375 | * @var boolean $required 376 | */ 377 | var $required; 378 | 379 | /** 380 | * Error associated with the element 381 | * @var string $error 382 | */ 383 | var $error; 384 | 385 | /** 386 | * Some information about element style 387 | * @var string $style 388 | */ 389 | var $style; 390 | 391 | /** 392 | * HTML for the element 393 | * @var string $html 394 | */ 395 | var $html; 396 | 397 | /** 398 | * If element is a group, the group separator 399 | * @var mixed $separator 400 | */ 401 | var $separator; 402 | 403 | /** 404 | * If element is a group, an array of subelements 405 | * @var array $elements 406 | */ 407 | var $elements; 408 | 409 | function isType($type) 410 | { 411 | return ($this->type == $type); 412 | } 413 | 414 | function notFrozen() 415 | { 416 | return !$this->frozen; 417 | } 418 | 419 | function isButton() 420 | { 421 | return ($this->type == "submit" || $this->type == "reset"); 422 | } 423 | 424 | 425 | /** 426 | * XXX: why does it use Flexy when all other stuff here does not depend on it? 427 | */ 428 | function outputStyle() 429 | { 430 | ob_start(); 431 | HTML_Template_Flexy::staticQuickTemplate('styles/' . $this->style . '.html', $this); 432 | $ret = ob_get_contents(); 433 | ob_end_clean(); 434 | return $ret; 435 | } 436 | } 437 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/Renderer/ObjectFlexy.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2001-2011 The PHP Group 6 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 7 | */ 8 | 9 | /** 10 | * QuickForm renderer for Flexy template engine, static version. 11 | * 12 | * A static renderer for HTML_Quickform. Makes a QuickFormFlexyObject 13 | * from the form content suitable for use with a Flexy template 14 | * 15 | * Usage: 16 | * 17 | * $form = new HTML_QuickForm('form', 'POST'); 18 | * $template = new HTML_Template_Flexy(); 19 | * $renderer = new HTML_QuickForm_Renderer_ObjectFlexy(&$template); 20 | * $renderer->setHtmlTemplate("html.html"); 21 | * $renderer->setLabelTemplate("label.html"); 22 | * $form->accept($renderer); 23 | * $view = new StdClass; 24 | * $view->form = $renderer->toObject(); 25 | * $template->compile("mytemplate.html"); 26 | * 27 | * 28 | * Based on the code for HTML_QuickForm_Renderer_ArraySmarty 29 | * 30 | * @package HTML_QuickForm 31 | * @author Ron McClain 32 | */ 33 | class HTML_QuickForm_Renderer_ObjectFlexy extends HTML_QuickForm_Renderer_Object 34 | { 35 | /**#@+ 36 | * @access private 37 | */ 38 | /** 39 | * HTML_Template_Flexy instance 40 | * @var object $_flexy 41 | */ 42 | var $_flexy; 43 | 44 | /** 45 | * Current element index 46 | * @var integer $_elementIdx 47 | */ 48 | var $_elementIdx; 49 | 50 | /** 51 | * The current element index inside a group 52 | * @var integer $_groupElementIdx 53 | */ 54 | var $_groupElementIdx = 0; 55 | 56 | /** 57 | * Name of template file for form html 58 | * @var string $_html 59 | * @see setRequiredTemplate() 60 | */ 61 | var $_html = ''; 62 | 63 | /** 64 | * Name of template file for form labels 65 | * @var string $label 66 | * @see setErrorTemplate() 67 | */ 68 | var $label = ''; 69 | 70 | /** 71 | * Class of the element objects, so you can add your own 72 | * element methods 73 | * @var string $_elementType 74 | */ 75 | var $_elementType = 'QuickformFlexyElement'; 76 | /**#@-*/ 77 | 78 | /** 79 | * Constructor 80 | * 81 | * @param HTML_Template_Flexy template object to use 82 | */ 83 | public function __construct(&$flexy) 84 | { 85 | parent::__construct(true); 86 | $this->_obj = new QuickformFlexyForm(); 87 | $this->_flexy =& $flexy; 88 | } 89 | 90 | public function renderHtml(&$data) 91 | { 92 | } 93 | 94 | public function finishForm(&$form) 95 | { 96 | } 97 | 98 | function renderHeader(&$header) 99 | { 100 | if($name = $header->getName()) { 101 | $this->_obj->header->$name = $header->toHtml(); 102 | } else { 103 | $this->_obj->header[$this->_sectionCount] = $header->toHtml(); 104 | } 105 | $this->_currentSection = $this->_sectionCount++; 106 | } 107 | 108 | function startGroup(&$group, $required, $error) 109 | { 110 | parent::startGroup($group, $required, $error); 111 | $this->_groupElementIdx = 1; 112 | } 113 | 114 | /** 115 | * Creates an object representing an element containing 116 | * the key for storing this 117 | * 118 | * @access private 119 | * @param HTML_QuickForm_element form element being rendered 120 | * @param bool Whether an element is required 121 | * @param string Error associated with the element 122 | * @return object 123 | */ 124 | function _elementToObject(&$element, $required, $error) 125 | { 126 | $ret = parent::_elementToObject($element, $required, $error); 127 | if($ret->type == 'group') { 128 | $ret->html = $element->toHtml(); 129 | unset($ret->elements); 130 | } 131 | if(!empty($this->_label)) { 132 | $this->_renderLabel($ret); 133 | } 134 | 135 | if(!empty($this->_html)) { 136 | $this->_renderHtml($ret); 137 | $ret->error = $error; 138 | } 139 | 140 | // Create an element key from the name 141 | if (false !== ($pos = strpos($ret->name, '[')) || is_object($this->_currentGroup)) { 142 | if (!$pos) { 143 | $keys = '->{\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $ret->name) . '\'}'; 144 | } else { 145 | $keys = '->{\'' . str_replace( 146 | array('\\', '\'', '[', ']'), array('\\\\', '\\\'', '\'}->{\'', ''), 147 | $ret->name 148 | ) . '\'}'; 149 | } 150 | // special handling for elements in native groups 151 | if (is_object($this->_currentGroup)) { 152 | // skip unnamed group items unless radios: no name -> no static access 153 | // identification: have the same key string as the parent group 154 | if ($this->_currentGroup->keys == $keys && 'radio' != $ret->type) { 155 | return false; 156 | } 157 | // reduce string of keys by remove leading group keys 158 | if (0 === strpos($keys, $this->_currentGroup->keys)) { 159 | $keys = substr_replace($keys, '', 0, strlen($this->_currentGroup->keys)); 160 | } 161 | } 162 | } elseif (0 == strlen($ret->name)) { 163 | $keys = '->{\'element_' . $this->_elementIdx . '\'}'; 164 | } else { 165 | $keys = '->{\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $ret->name) . '\'}'; 166 | } 167 | // for radios: add extra key from value 168 | if ('radio' == $ret->type && '[]' != substr($keys, -2)) { 169 | $keys .= '->{\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $ret->value) . '\'}'; 170 | } 171 | $ret->keys = $keys; 172 | $this->_elementIdx++; 173 | return $ret; 174 | } 175 | 176 | /** 177 | * Stores an object representation of an element in the 178 | * QuickformFormObject instance 179 | * 180 | * @access private 181 | * @param QuickformElement Object representation of an element 182 | */ 183 | function _storeObject($elObj) 184 | { 185 | if ($elObj) { 186 | $keys = $elObj->keys; 187 | unset($elObj->keys); 188 | if(is_object($this->_currentGroup) && ('group' != $elObj->type)) { 189 | $code = '$this->_currentGroup' . $keys . ' = $elObj;'; 190 | } else { 191 | $code = '$this->_obj' . $keys . ' = $elObj;'; 192 | } 193 | eval($code); 194 | } 195 | } 196 | 197 | /** 198 | * Set the filename of the template to render html elements. 199 | * In your template, {html} is replaced by the unmodified html. 200 | * If the element is required, {required} will be true. 201 | * Eg. 202 | *
203 |      * {if:error}
204 |      *   {error:h}
205 | * {end:} 206 | * {html:h} 207 | *
208 | * 209 | * @param string Filename of template 210 | */ 211 | public function setHtmlTemplate($template) 212 | { 213 | $this->_html = $template; 214 | } 215 | 216 | /** 217 | * Set the filename of the template to render form labels 218 | * In your template, {label} is replaced by the unmodified label. 219 | * {error} will be set to the error, if any. {required} will 220 | * be true if this is a required field 221 | * Eg. 222 | *
223 |      * {if:required}
224 |      * *
225 |      * {end:}
226 |      * {label:h}
227 |      * 
228 | * 229 | * @param string Filename of template 230 | */ 231 | public function setLabelTemplate($template) 232 | { 233 | $this->_label = $template; 234 | } 235 | 236 | function _renderLabel(&$ret) 237 | { 238 | $this->_flexy->compile($this->_label); 239 | $ret->label = $this->_flexy->bufferedOutputObject($ret); 240 | } 241 | 242 | function _renderHtml(&$ret) 243 | { 244 | $this->_flexy->compile($this->_html); 245 | $ret->html = $this->_flexy->bufferedOutputObject($ret); 246 | } 247 | } 248 | 249 | /** 250 | * Adds nothing to QuickformForm, left for backwards compatibility 251 | * 252 | * @package HTML_QuickForm 253 | * @ignore 254 | */ 255 | class QuickformFlexyForm extends QuickformForm 256 | { 257 | } 258 | 259 | /** 260 | * Adds nothing to QuickformElement, left for backwards compatibility 261 | * 262 | * @package HTML_QuickForm 263 | * @ignore 264 | */ 265 | class QuickformFlexyElement extends QuickformElement 266 | { 267 | } 268 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/Renderer/QuickHtml.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2001-2011 The PHP Group 6 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 7 | */ 8 | 9 | /** 10 | * A renderer that makes it quick and easy to create customized forms. 11 | * 12 | * This renderer has three main distinctives: an easy way to create 13 | * custom-looking forms, the ability to separate the creation of form 14 | * elements from their display, and being able to use QuickForm in 15 | * widget-based template systems. See the online docs for more info. 16 | * For a usage example see: docs/renderers/QuickHtml_example.php 17 | * 18 | * @package HTML_QuickForm 19 | * @author Jason Rust 20 | */ 21 | class HTML_QuickForm_Renderer_QuickHtml extends HTML_QuickForm_Renderer_Default 22 | { 23 | /** 24 | * The array of rendered elements 25 | * @var array 26 | */ 27 | var $renderedElements = array(); 28 | 29 | /** 30 | * Constructor 31 | */ 32 | public function __construct() 33 | { 34 | // The default templates aren't used for this renderer 35 | $this->clearAllTemplates(); 36 | } 37 | 38 | /** 39 | * returns the HTML generated for the form 40 | * 41 | * @param string $data (optional) Any extra data to put before the end of the form 42 | * @return string 43 | */ 44 | public function toHtml($data = '') 45 | { 46 | // Render any elements that haven't been rendered explicitly by elementToHtml() 47 | foreach (array_keys($this->renderedElements) as $key) { 48 | if (!$this->renderedElements[$key]['rendered']) { 49 | $this->renderedElements[$key]['rendered'] = true; 50 | $data .= $this->renderedElements[$key]['html'] . "\n"; 51 | } 52 | } 53 | 54 | // Insert the extra data and form elements at the end of the form 55 | $this->_html = str_replace('', $data . "\n", $this->_html); 56 | return $this->_html; 57 | } 58 | 59 | /** 60 | * Gets the html for an element and marks it as rendered. 61 | * 62 | * @param string $elementName The element name 63 | * @param string $elementValue (optional) The value of the element. This is only useful 64 | * for elements that have the same name (i.e. radio and checkbox), but 65 | * different values 66 | * 67 | * @return string The html for the QuickForm element 68 | * @throws HTML_QuickForm_Error 69 | */ 70 | public function elementToHtml($elementName, $elementValue = null) 71 | { 72 | $elementKey = null; 73 | // Find the key for the element 74 | foreach ($this->renderedElements as $key => $data) { 75 | if ($data['name'] == $elementName && 76 | // See if the value must match as well 77 | (is_null($elementValue) || 78 | $data['value'] == $elementValue)) { 79 | $elementKey = $key; 80 | break; 81 | } 82 | } 83 | 84 | if (is_null($elementKey)) { 85 | $msg = is_null($elementValue) ? "Element $elementName does not exist." : 86 | "Element $elementName with value of $elementValue does not exist."; 87 | throw new HTML_QuickForm_Error($msg, QUICKFORM_UNREGISTERED_ELEMENT); 88 | } else { 89 | if ($this->renderedElements[$elementKey]['rendered']) { 90 | $msg = is_null($elementValue) ? "Element $elementName has already been rendered." : 91 | "Element $elementName with value of $elementValue has already been rendered."; 92 | throw new HTML_QuickForm_Error($msg, QUICKFORM_ERROR); 93 | } else { 94 | $this->renderedElements[$elementKey]['rendered'] = true; 95 | return $this->renderedElements[$elementKey]['html']; 96 | } 97 | } 98 | } 99 | 100 | /** 101 | * Gets the html for an element and adds it to the array by calling 102 | * parent::renderElement() 103 | * 104 | * @param HTML_QuickForm_element form element being visited 105 | * @param bool Whether an element is required 106 | * @param string An error message associated with an element 107 | * 108 | * @return mixed HTML string of element if $immediateRender is set, else we just add the 109 | * html to the global _html string 110 | */ 111 | public function renderElement(&$element, $required, $error) 112 | { 113 | $this->_html = ''; 114 | parent::renderElement($element, $required, $error); 115 | if (!$this->_inGroup) { 116 | $this->renderedElements[] = array( 117 | 'name' => $element->getName(), 118 | 'value' => $element->getValue(), 119 | 'html' => $this->_html, 120 | 'rendered' => false); 121 | } 122 | $this->_html = ''; 123 | } 124 | 125 | /** 126 | * @inheritDoc 127 | */ 128 | public function renderHidden(&$element, $required, $error) 129 | { 130 | $this->renderedElements[] = array( 131 | 'name' => $element->getName(), 132 | 'value' => $element->getValue(), 133 | 'html' => $element->toHtml(), 134 | 'rendered' => false); 135 | } 136 | 137 | /** 138 | * Gets the html for the group element and adds it to the array by calling 139 | * parent::finishGroup() 140 | * 141 | * @param HTML_QuickForm_group group being visited 142 | */ 143 | public function finishGroup(&$group) 144 | { 145 | $this->_html = ''; 146 | parent::finishGroup($group); 147 | $this->renderedElements[] = array( 148 | 'name' => $group->getName(), 149 | 'value' => $group->getValue(), 150 | 'html' => $this->_html, 151 | 'rendered' => false); 152 | $this->_html = ''; 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/Rule.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2001-2011 The PHP Group 6 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 7 | */ 8 | 9 | /** 10 | * Abstract base class for QuickForm validation rules 11 | * 12 | * @package HTML_QuickForm 13 | * @author Bertrand Mansion 14 | */ 15 | abstract class HTML_QuickForm_Rule 16 | { 17 | /** 18 | * Name of the rule to use in validate method 19 | * 20 | * This property is used in more global rules like Callback and Regex 21 | * to determine which callback and which regex is to be used for validation 22 | * 23 | * @var string 24 | */ 25 | public $name; 26 | 27 | /** 28 | * Validates a value 29 | * 30 | * @param string $value Value to be checked 31 | * @param mixed $options Int for length, array for range 32 | * @return boolean true if value is valid 33 | */ 34 | abstract public function validate($value, $options = null); 35 | 36 | /** 37 | * Sets the rule name 38 | * 39 | * @param string rule name 40 | */ 41 | public function setName($ruleName) 42 | { 43 | $this->name = $ruleName; 44 | } 45 | 46 | /** 47 | * Returns the javascript test (the test should return true if the value is INVALID) 48 | * 49 | * @param mixed Options for the rule 50 | * @return array first element is code to setup validation, second is the check itself 51 | * @abstract 52 | */ 53 | public function getValidationScript($options = null) 54 | { 55 | return array('', ''); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/Rule/Callback.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2001-2011 The PHP Group 6 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 7 | */ 8 | 9 | /** 10 | * Validates values using callback functions or methods 11 | * 12 | * @package HTML_QuickForm 13 | * @author Bertrand Mansion 14 | */ 15 | class HTML_QuickForm_Rule_Callback extends HTML_QuickForm_Rule 16 | { 17 | /** 18 | * Array of callbacks 19 | * 20 | * Array is in the format: 21 | * $_data['rulename'] = array('functionname', 'classname'); 22 | * If the callback is not a method, then the class name is not set. 23 | * 24 | * @var array 25 | * @access private 26 | */ 27 | var $_data = array(); 28 | 29 | /** 30 | * Whether to use BC mode for specific rules 31 | * 32 | * Previous versions of QF passed element's name as a first parameter 33 | * to validation functions, but not to validation methods. This behaviour 34 | * is emulated if you are using 'function' as rule type when registering. 35 | * 36 | * @var array 37 | * @access private 38 | */ 39 | var $_BCMode = array(); 40 | 41 | /** 42 | * Validates a value using a callback 43 | * 44 | * @param string $value Value to be checked 45 | * @param mixed $options Options for callback 46 | * @return boolean true if value is valid 47 | */ 48 | public function validate($value, $options = null) 49 | { 50 | if (isset($this->_data[$this->name])) { 51 | $callback = $this->_data[$this->name]; 52 | if (isset($callback[1])) { 53 | return call_user_func(array($callback[1], $callback[0]), $value, $options); 54 | } elseif ($this->_BCMode[$this->name]) { 55 | return $callback[0]('', $value, $options); 56 | } else { 57 | return $callback[0]($value, $options); 58 | } 59 | } elseif (is_callable($options)) { 60 | return call_user_func($options, $value); 61 | } else { 62 | return true; 63 | } 64 | } 65 | 66 | /** 67 | * Adds new callbacks to the callbacks list 68 | * 69 | * @param string $name Name of rule 70 | * @param string $callback Name of function or method 71 | * @param string $class Name of class containing the method 72 | * @param bool $BCMode Backwards compatibility mode 73 | */ 74 | public function addData($name, $callback, $class = null, $BCMode = false) 75 | { 76 | if (!empty($class)) { 77 | $this->_data[$name] = array($callback, $class); 78 | } else { 79 | $this->_data[$name] = array($callback); 80 | } 81 | $this->_BCMode[$name] = $BCMode; 82 | } 83 | 84 | 85 | function getValidationScript($options = null) 86 | { 87 | if (isset($this->_data[$this->name])) { 88 | $callback = $this->_data[$this->name][0]; 89 | $params = ($this->_BCMode[$this->name]? "'', {jsVar}": '{jsVar}') . 90 | (isset($options)? ", '{$options}'": ''); 91 | } else { 92 | $callback = is_array($options)? $options[1]: $options; 93 | $params = '{jsVar}'; 94 | } 95 | return array('', "{jsVar} != '' && !{$callback}({$params})"); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/Rule/Compare.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2001-2011 The PHP Group 6 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 7 | */ 8 | 9 | /** 10 | * Rule to compare two form fields 11 | * 12 | * The most common usage for this is to ensure that the password 13 | * confirmation field matches the password field 14 | * 15 | * @package HTML_QuickForm 16 | * @author Alexey Borzov 17 | */ 18 | class HTML_QuickForm_Rule_Compare extends HTML_QuickForm_Rule 19 | { 20 | /** 21 | * Possible operators to use 22 | * @var array 23 | * @access private 24 | */ 25 | var $_operators = array( 26 | 'eq' => '===', 27 | 'neq' => '!==', 28 | 'gt' => '>', 29 | 'gte' => '>=', 30 | 'lt' => '<', 31 | 'lte' => '<=', 32 | '==' => '===', 33 | '!=' => '!==' 34 | ); 35 | 36 | 37 | /** 38 | * Returns the operator to use for comparing the values 39 | * 40 | * @access private 41 | * @param string operator name 42 | * @return string operator to use for validation 43 | */ 44 | function _findOperator($name) 45 | { 46 | if (empty($name)) { 47 | return '==='; 48 | } elseif (isset($this->_operators[$name])) { 49 | return $this->_operators[$name]; 50 | } elseif (in_array($name, $this->_operators)) { 51 | return $name; 52 | } else { 53 | return '==='; 54 | } 55 | } 56 | 57 | function validate($values, $operator = null) 58 | { 59 | if (!array_key_exists(0, $values) || !array_key_exists(1, $values) || !is_scalar($values[0]) || !is_scalar($values[1])) { 60 | return false; 61 | } 62 | switch ($this->_findOperator($operator)) { 63 | case '===': 64 | return strval($values[0]) === strval($values[1]); 65 | case '!==': 66 | return strval($values[0]) !== strval($values[1]); 67 | case '>': 68 | return floatval($values[0]) > floatval($values[1]); 69 | case '>=': 70 | return floatval($values[0]) >= floatval($values[1]); 71 | case '<': 72 | return floatval($values[0]) < floatval($values[1]); 73 | case '<=': 74 | return floatval($values[0]) <= floatval($values[1]); 75 | } 76 | } 77 | 78 | 79 | function getValidationScript($operator = null) 80 | { 81 | $operator = $this->_findOperator($operator); 82 | if ('===' != $operator && '!==' != $operator) { 83 | $check = "!(Number({jsVar}[0]) {$operator} Number({jsVar}[1]))"; 84 | } else { 85 | $check = "!(String({jsVar}[0]) {$operator} String({jsVar}[1]))"; 86 | } 87 | return array('', "'' != {jsVar}[0] && {$check}"); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/Rule/Email.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2001-2011 The PHP Group 6 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 7 | */ 8 | 9 | /** 10 | * Email validation rule 11 | * 12 | * @category HTML 13 | * @package HTML_QuickForm 14 | * @author Bertrand Mansion 15 | */ 16 | class HTML_QuickForm_Rule_Email extends HTML_QuickForm_Rule 17 | { 18 | var $regex = '/^((\"[^\"\f\n\r\t\v\b]+\")|([\w\!\#\$\%\&\'\*\+\-\~\/\^\`\|\{\}]+(\.[\w\!\#\$\%\&\'\*\+\-\~\/\^\`\|\{\}]+)*))@((\[(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))\])|(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))|((([A-Za-z0-9\-])+\.)+[A-Za-z\-]+))$/'; 19 | 20 | /** 21 | * Validates an email address 22 | * 23 | * @param string $email Email address 24 | * @param boolean $checkDomain True if dns check should be performed 25 | * @return boolean true if email is valid 26 | */ 27 | public function validate($email, $checkDomain = null) 28 | { 29 | if (!is_scalar($email)) { 30 | return false; 31 | } 32 | // Fix for bug #10799: add 'D' modifier to regex 33 | if (preg_match($this->regex . 'D', $email)) { 34 | if ($checkDomain && function_exists('checkdnsrr')) { 35 | $tokens = explode('@', $email); 36 | if (checkdnsrr($tokens[1], 'MX') || checkdnsrr($tokens[1], 'A')) { 37 | return true; 38 | } 39 | return false; 40 | } 41 | return true; 42 | } 43 | return false; 44 | } 45 | 46 | function getValidationScript($options = null) 47 | { 48 | return array(" var regex = " . $this->regex . ";\n", "{jsVar} != '' && !regex.test({jsVar})"); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/Rule/Range.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2001-2011 The PHP Group 6 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 7 | */ 8 | 9 | /** 10 | * Checks that the length of value is within range 11 | * 12 | * @package HTML_QuickForm 13 | * @author Bertrand Mansion 14 | */ 15 | class HTML_QuickForm_Rule_Range extends HTML_QuickForm_Rule 16 | { 17 | /** 18 | * @inheritdoc 19 | * 20 | * Validates a value using a range comparison 21 | */ 22 | public function validate($value, $options = null) 23 | { 24 | if (!is_scalar($value)) { 25 | return false; 26 | } 27 | $length = strlen($value); 28 | switch ($this->name) { 29 | case 'minlength': return ($length >= $options); 30 | case 'maxlength': return ($length <= $options); 31 | default: return ($length >= $options[0] && $length <= $options[1]); 32 | } 33 | } 34 | 35 | function getValidationScript($options = null) 36 | { 37 | switch ($this->name) { 38 | case 'minlength': 39 | $test = '{jsVar}.length < '.$options; 40 | break; 41 | case 'maxlength': 42 | $test = '{jsVar}.length > '.$options; 43 | break; 44 | default: 45 | $test = '({jsVar}.length < '.$options[0].' || {jsVar}.length > '.$options[1].')'; 46 | } 47 | return array('', "{jsVar} != '' && {$test}"); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/Rule/Regex.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2001-2011 The PHP Group 6 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 7 | */ 8 | 9 | /** 10 | * Validates values using regular expressions 11 | * 12 | * @package HTML_QuickForm 13 | * @author Bertrand Mansion 14 | */ 15 | class HTML_QuickForm_Rule_Regex extends HTML_QuickForm_Rule 16 | { 17 | /** 18 | * Array of regular expressions 19 | * 20 | * Array is in the format: 21 | * $_data['rulename'] = 'pattern'; 22 | * 23 | * @var array 24 | * @access private 25 | */ 26 | var $_data = array( 27 | 'lettersonly' => '/^[a-zA-Z]+$/', 28 | 'alphanumeric' => '/^[a-zA-Z0-9]+$/', 29 | 'numeric' => '/(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)/', 30 | 'nopunctuation' => '/^[^().\/\*\^\?#!@$%+=,\"\'><~\[\]{}]+$/', 31 | 'nonzero' => '/^-?[1-9][0-9]*/' 32 | ); 33 | 34 | /** 35 | * Validates a value using a regular expression 36 | * 37 | * @param string $value Value to be checked 38 | * @param string $regex Regular expression 39 | * @return boolean true if value is valid 40 | */ 41 | public function validate($value, $regex = null) 42 | { 43 | if (!is_scalar($value)) { 44 | return false; 45 | } 46 | // Fix for bug #10799: add 'D' modifier to regex 47 | if (isset($this->_data[$this->name])) { 48 | if (!preg_match($this->_data[$this->name] . 'D', $value)) { 49 | return false; 50 | } 51 | } else { 52 | if (!preg_match($regex . 'D', $value)) { 53 | return false; 54 | } 55 | } 56 | return true; 57 | } 58 | 59 | /** 60 | * Adds new regular expressions to the list 61 | * 62 | * @param string $name Name of rule 63 | * @param string $pattern Regular expression pattern 64 | */ 65 | public function addData($name, $pattern) 66 | { 67 | $this->_data[$name] = $pattern; 68 | } 69 | 70 | function getValidationScript($options = null) 71 | { 72 | $regex = isset($this->_data[$this->name]) ? $this->_data[$this->name] : $options; 73 | 74 | // bug #12376, converting unicode escapes and stripping 'u' modifier 75 | if ($pos = strpos($regex, 'u', strrpos($regex, '/'))) { 76 | $regex = substr($regex, 0, $pos) . substr($regex, $pos + 1); 77 | $regex = preg_replace('/(?\\\\\\\\)*\\\\x{([a-fA-F0-9]+)}/', '\\u$1', $regex); 78 | } 79 | 80 | return array(" var regex = " . $regex . ";\n", "{jsVar} != '' && !regex.test({jsVar})"); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/Rule/Required.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2001-2011 The PHP Group 6 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 7 | */ 8 | 9 | /** 10 | * Required elements validation 11 | * 12 | * @package HTML_QuickForm 13 | * @author Bertrand Mansion 14 | */ 15 | class HTML_QuickForm_Rule_Required extends HTML_QuickForm_Rule 16 | { 17 | /** 18 | * Checks if an element is empty 19 | * 20 | * @param string $value Value to check 21 | * @param mixed $options Not used yet 22 | * @return boolean true if value is not empty 23 | */ 24 | public function validate($value, $options = null) 25 | { 26 | if (is_array($value)) 27 | { 28 | return !empty($value); 29 | } 30 | if ((string)$value == '') { 31 | return false; 32 | } 33 | return true; 34 | } 35 | 36 | function getValidationScript($options = null) 37 | { 38 | return array('', "{jsVar} == ''"); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/RuleRegistry.php: -------------------------------------------------------------------------------- 1 | 5 | * @author Bertrand Mansion 6 | * @author Alexey Borzov 7 | * @copyright 2001-2011 The PHP Group 8 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 9 | */ 10 | 11 | /** 12 | * Registers rule objects and uses them for validation 13 | * 14 | * @package HTML_QuickForm 15 | * @author Adam Daniel 16 | * @author Bertrand Mansion 17 | * @author Alexey Borzov 18 | */ 19 | class HTML_QuickForm_RuleRegistry 20 | { 21 | /** 22 | * Array containing references to used rules 23 | * @var array 24 | * @access private 25 | */ 26 | var $_rules = array(); 27 | 28 | /** 29 | * Returns a singleton of HTML_QuickForm_RuleRegistry 30 | * 31 | * Usually, only one RuleRegistry object is needed, this is the reason 32 | * why it is recommended to use this method to get the validation object. 33 | * 34 | * @return HTML_QuickForm_RuleRegistry 35 | */ 36 | public static function &singleton() 37 | { 38 | static $obj; 39 | if (!isset($obj)) { 40 | $obj = new HTML_QuickForm_RuleRegistry(); 41 | } 42 | return $obj; 43 | } 44 | 45 | /** 46 | * Registers a new validation rule 47 | * 48 | * In order to use a custom rule in your form, you need to register it 49 | * first. For regular expressions, one can directly use the 'regex' type 50 | * rule in addRule(), this is faster than registering the rule. 51 | * 52 | * Functions and methods can be registered. Use the 'function' type. 53 | * When registering a method, specify the class name as second parameter. 54 | * 55 | * You can also register an HTML_QuickForm_Rule subclass with its own 56 | * validate() method. 57 | * 58 | * @param string $ruleName Name of validation rule 59 | * @param string $type Either: 'regex', 'function' or null 60 | * @param string $data1 Name of function, regular expression or 61 | * HTML_QuickForm_Rule object class name 62 | * @param string $data2 Object parent of above function 63 | */ 64 | public function registerRule($ruleName, $type, $data1, $data2 = null) 65 | { 66 | $type = strtolower((string) $type); 67 | if ($type == 'regex') { 68 | // Regular expression 69 | $rule =& $this->getRule('regex'); 70 | $rule->addData($ruleName, $data1); 71 | $GLOBALS['_HTML_QuickForm_registered_rules'][$ruleName] = $GLOBALS['_HTML_QuickForm_registered_rules']['regex']; 72 | 73 | } elseif ($type == 'function' || $type == 'callback') { 74 | // Callback function 75 | $rule =& $this->getRule('callback'); 76 | $rule->addData($ruleName, $data1, $data2, 'function' == $type); 77 | $GLOBALS['_HTML_QuickForm_registered_rules'][$ruleName] = $GLOBALS['_HTML_QuickForm_registered_rules']['callback']; 78 | 79 | } elseif (is_object($data1)) { 80 | // An instance of HTML_QuickForm_Rule 81 | $this->_rules[strtolower(get_class($data1))] = $data1; 82 | $GLOBALS['_HTML_QuickForm_registered_rules'][$ruleName] = strtolower(get_class($data1)); 83 | 84 | } else { 85 | // Rule class name 86 | $GLOBALS['_HTML_QuickForm_registered_rules'][$ruleName] = strtolower($data1); 87 | } 88 | } 89 | 90 | /** 91 | * Returns a reference to the requested rule object 92 | * 93 | * @param string $ruleName Name of the requested rule 94 | * @return HTML_QuickForm_Rule 95 | */ 96 | public function &getRule($ruleName) 97 | { 98 | $class = $GLOBALS['_HTML_QuickForm_registered_rules'][$ruleName]; 99 | 100 | if (!isset($this->_rules[$class])) { 101 | $this->_rules[$class] = new $class(); 102 | } 103 | $this->_rules[$class]->setName($ruleName); 104 | return $this->_rules[$class]; 105 | } 106 | 107 | /** 108 | * Performs validation on the given values 109 | * 110 | * @param string $ruleName Name of the rule to be used 111 | * @param mixed $values Can be a scalar or an array of values 112 | * to be validated 113 | * @param mixed $options Options used by the rule 114 | * @param mixed $multiple Whether to validate an array of values altogether 115 | * @return mixed true if no error found, int of valid values (when an array of values is given) or false if error 116 | */ 117 | public function validate($ruleName, $values, $options = null, $multiple = false) 118 | { 119 | $rule =& $this->getRule($ruleName); 120 | 121 | if (is_array($values) && !$multiple) { 122 | $result = 0; 123 | foreach ($values as $value) { 124 | if ($rule->validate($value, $options) === true) { 125 | $result++; 126 | } 127 | } 128 | return ($result == 0) ? false : $result; 129 | } else { 130 | return $rule->validate($values, $options); 131 | } 132 | } 133 | 134 | /** 135 | * Returns the validation test in javascript code 136 | * 137 | * @param array|HTML_QuickForm_element Element(s) the rule applies to 138 | * @param string Element name, in case $element is 139 | * not an array 140 | * @param array Rule data 141 | * @return string JavaScript for the rule 142 | */ 143 | public function getValidationScript(&$element, $elementName, $ruleData) 144 | { 145 | $reset = (isset($ruleData['reset'])) ? $ruleData['reset'] : false; 146 | $rule =& $this->getRule($ruleData['type']); 147 | if (!is_array($element)) { 148 | list($jsValue, $jsReset) = $this->_getJsValue($element, $elementName, $reset, null); 149 | } else { 150 | $jsValue = " value = new Array();\n"; 151 | $jsReset = ''; 152 | for ($i = 0; $i < count($element); $i++) { 153 | list($tmp_value, $tmp_reset) = $this->_getJsValue($element[$i], $element[$i]->getName(), $reset, $i); 154 | $jsValue .= "\n" . $tmp_value; 155 | $jsReset .= $tmp_reset; 156 | } 157 | } 158 | $jsField = isset($ruleData['group'])? $ruleData['group']: $elementName; 159 | list ($jsPrefix, $jsCheck) = $rule->getValidationScript($ruleData['format']); 160 | if (!isset($ruleData['howmany'])) { 161 | $js = $jsValue . "\n" . $jsPrefix . 162 | " if (" . str_replace('{jsVar}', 'value', $jsCheck) . " && !errFlag['{$jsField}']) {\n" . 163 | " errFlag['{$jsField}'] = true;\n" . 164 | " _qfMsg = _qfMsg + '\\n - {$ruleData['message']}';\n" . 165 | $jsReset . 166 | " }\n"; 167 | } else { 168 | $js = $jsValue . "\n" . $jsPrefix . 169 | " var res = 0;\n" . 170 | " for (var i = 0; i < value.length; i++) {\n" . 171 | " if (!(" . str_replace('{jsVar}', 'value[i]', $jsCheck) . ")) {\n" . 172 | " res++;\n" . 173 | " }\n" . 174 | " }\n" . 175 | " if (res < {$ruleData['howmany']} && !errFlag['{$jsField}']) {\n" . 176 | " errFlag['{$jsField}'] = true;\n" . 177 | " _qfMsg = _qfMsg + '\\n - {$ruleData['message']}';\n" . 178 | $jsReset . 179 | " }\n"; 180 | } 181 | return $js; 182 | } 183 | 184 | /** 185 | * Returns JavaScript to get and to reset the element's value 186 | * 187 | * @access private 188 | * @param HTML_QuickForm_element element being processed 189 | * @param string element's name 190 | * @param bool whether to generate JavaScript to reset 191 | * the value 192 | * @param integer value's index in the array (only used for 193 | * multielement rules) 194 | * @return array first item is value javascript, second is reset 195 | */ 196 | function _getJsValue(&$element, $elementName, $reset = false, $index = null) 197 | { 198 | $jsIndex = isset($index)? '[' . $index . ']': ''; 199 | $tmp_reset = $reset? " var field = frm.elements['$elementName'];\n": ''; 200 | if (is_a($element, 'html_quickform_group')) { 201 | $value = " _qfGroups['{$elementName}'] = {"; 202 | $elements =& $element->getElements(); 203 | for ($i = 0, $count = count($elements); $i < $count; $i++) { 204 | $append = ($elements[$i]->getType() == 'select' && $elements[$i]->getMultiple())? '[]': ''; 205 | $value .= "'" . $element->getElementName($i) . $append . "': true" . 206 | ($i < $count - 1? ', ': ''); 207 | } 208 | $value .= 209 | "};\n" . 210 | " value{$jsIndex} = new Array();\n" . 211 | " var valueIdx = 0;\n" . 212 | " for (var i = 0; i < frm.elements.length; i++) {\n" . 213 | " var _element = frm.elements[i];\n" . 214 | " if (_element.name in _qfGroups['{$elementName}']) {\n" . 215 | " switch (_element.type) {\n" . 216 | " case 'checkbox':\n" . 217 | " case 'radio':\n" . 218 | " if (_element.checked) {\n" . 219 | " value{$jsIndex}[valueIdx++] = _element.value;\n" . 220 | " }\n" . 221 | " break;\n" . 222 | " case 'select-one':\n" . 223 | " if (-1 != _element.selectedIndex) {\n" . 224 | " value{$jsIndex}[valueIdx++] = _element.options[_element.selectedIndex].value;\n" . 225 | " }\n" . 226 | " break;\n" . 227 | " case 'select-multiple':\n" . 228 | " var tmpVal = new Array();\n" . 229 | " var tmpIdx = 0;\n" . 230 | " for (var j = 0; j < _element.options.length; j++) {\n" . 231 | " if (_element.options[j].selected) {\n" . 232 | " tmpVal[tmpIdx++] = _element.options[j].value;\n" . 233 | " }\n" . 234 | " }\n" . 235 | " if (tmpIdx > 0) {\n" . 236 | " value{$jsIndex}[valueIdx++] = tmpVal;\n" . 237 | " }\n" . 238 | " break;\n" . 239 | " default:\n" . 240 | " value{$jsIndex}[valueIdx++] = _element.value;\n" . 241 | " }\n" . 242 | " }\n" . 243 | " }\n"; 244 | if ($reset) { 245 | $tmp_reset = 246 | " for (var i = 0; i < frm.elements.length; i++) {\n" . 247 | " var _element = frm.elements[i];\n" . 248 | " if (_element.name in _qfGroups['{$elementName}']) {\n" . 249 | " switch (_element.type) {\n" . 250 | " case 'checkbox':\n" . 251 | " case 'radio':\n" . 252 | " _element.checked = _element.defaultChecked;\n" . 253 | " break;\n" . 254 | " case 'select-one':\n" . 255 | " case 'select-multiple':\n" . 256 | " for (var j = 0; j < _element.options.length; j++) {\n" . 257 | " _element.options[j].selected = _element.options[j].defaultSelected;\n" . 258 | " }\n" . 259 | " break;\n" . 260 | " default:\n" . 261 | " _element.value = _element.defaultValue;\n" . 262 | " }\n" . 263 | " }\n" . 264 | " }\n"; 265 | } 266 | 267 | } elseif ($element->getType() == 'select') { 268 | if ($element->getMultiple()) { 269 | $elementName .= '[]'; 270 | $value = 271 | " value{$jsIndex} = new Array();\n" . 272 | " var valueIdx = 0;\n" . 273 | " for (var i = 0; i < frm.elements['{$elementName}'].options.length; i++) {\n" . 274 | " if (frm.elements['{$elementName}'].options[i].selected) {\n" . 275 | " value{$jsIndex}[valueIdx++] = frm.elements['{$elementName}'].options[i].value;\n" . 276 | " }\n" . 277 | " }\n"; 278 | } else { 279 | $value = " value{$jsIndex} = frm.elements['{$elementName}'].selectedIndex == -1? '': frm.elements['{$elementName}'].options[frm.elements['{$elementName}'].selectedIndex].value;\n"; 280 | } 281 | if ($reset) { 282 | $tmp_reset .= 283 | " for (var i = 0; i < field.options.length; i++) {\n" . 284 | " field.options[i].selected = field.options[i].defaultSelected;\n" . 285 | " }\n"; 286 | } 287 | 288 | } elseif ($element->getType() == 'checkbox') { 289 | if (is_a($element, 'html_quickform_advcheckbox')) { 290 | $value = " value{$jsIndex} = frm.elements['$elementName'][1].checked? frm.elements['$elementName'][1].value: frm.elements['$elementName'][0].value;\n"; 291 | $tmp_reset .= $reset ? " field[1].checked = field[1].defaultChecked;\n" : ''; 292 | } else { 293 | $value = " value{$jsIndex} = frm.elements['$elementName'].checked? '1': '';\n"; 294 | $tmp_reset .= $reset ? " field.checked = field.defaultChecked;\n" : ''; 295 | } 296 | 297 | } elseif ($element->getType() == 'radio') { 298 | $value = " value{$jsIndex} = '';\n" . 299 | // Fix for bug #5644 300 | " var els = 'length' in frm.elements['$elementName']? frm.elements['$elementName']: [ frm.elements['$elementName'] ];\n" . 301 | " for (var i = 0; i < els.length; i++) {\n" . 302 | " if (els[i].checked) {\n" . 303 | " value{$jsIndex} = els[i].value;\n" . 304 | " }\n" . 305 | " }"; 306 | if ($reset) { 307 | $tmp_reset .= " for (var i = 0; i < field.length; i++) {\n" . 308 | " field[i].checked = field[i].defaultChecked;\n" . 309 | " }"; 310 | } 311 | 312 | } else { 313 | $value = " value{$jsIndex} = frm.elements['$elementName'].value;"; 314 | $tmp_reset .= ($reset) ? " field.value = field.defaultValue;\n" : ''; 315 | } 316 | return array($value, $tmp_reset); 317 | } 318 | } 319 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/advcheckbox.php: -------------------------------------------------------------------------------- 1 | 5 | * @author Alexey Borzov 6 | * @copyright 2001-2011 The PHP Group 7 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 8 | */ 9 | 10 | /** 11 | * HTML class for an advanced checkbox type field 12 | * 13 | * Basically this fixes a problem that HTML has had 14 | * where checkboxes can only pass a single value (the 15 | * value of the checkbox when checked). A value for when 16 | * the checkbox is not checked cannot be passed, and 17 | * furthermore the checkbox variable doesn't even exist if 18 | * the checkbox was submitted unchecked. 19 | * 20 | * It works by prepending a hidden field with the same name and 21 | * another "unchecked" value to the checbox. If the checkbox is 22 | * checked, PHP overwrites the value of the hidden field with 23 | * its value. 24 | * 25 | * @package HTML_QuickForm 26 | * @author Jason Rust 27 | * @author Alexey Borzov 28 | */ 29 | class HTML_QuickForm_advcheckbox extends HTML_QuickForm_checkbox 30 | { 31 | /** 32 | * The values passed by the hidden elment 33 | * 34 | * @var array 35 | * @access private 36 | */ 37 | var $_values = null; 38 | 39 | /** 40 | * The default value 41 | * 42 | * @var boolean 43 | * @access private 44 | */ 45 | var $_currentValue = null; 46 | 47 | /** 48 | * Class constructor 49 | * 50 | * @param string $elementName (optional)Input field name attribute 51 | * @param string $elementLabel (optional)Input field label 52 | * @param string $text (optional)Text to put after the checkbox 53 | * @param mixed $attributes (optional)Either a typical HTML attribute string 54 | * or an associative array 55 | * @param mixed $values (optional)Values to pass if checked or not checked 56 | * 57 | */ 58 | public function __construct($elementName=null, $elementLabel=null, $text='', $attributes=null, $values=null) 59 | { 60 | parent::__construct($elementName, $elementLabel, $text, $attributes); 61 | $this->setValues($values); 62 | } 63 | 64 | /** 65 | * Gets the private name for the element 66 | * 67 | * @param string $elementName The element name to make private 68 | * @return string 69 | * @deprecated Deprecated since 3.2.6, both generated elements have the same name 70 | */ 71 | public function getPrivateName($elementName) 72 | { 73 | return '__'.$elementName; 74 | } 75 | 76 | /** 77 | * Create the javascript for the onclick event which will 78 | * set the value of the hidden field 79 | * 80 | * @param string $elementName The element name 81 | * @return string 82 | * @deprecated Deprecated since 3.2.6, this element no longer uses any javascript 83 | */ 84 | public function getOnclickJs($elementName) 85 | { 86 | $onclickJs = 'if (this.checked) { this.form[\''.$elementName.'\'].value=\''.addcslashes($this->_values[1], '\'').'\'; }'; 87 | $onclickJs .= 'else { this.form[\''.$elementName.'\'].value=\''.addcslashes($this->_values[0], '\'').'\'; }'; 88 | return $onclickJs; 89 | } 90 | 91 | /** 92 | * Sets the values used by the hidden element 93 | * 94 | * @param mixed $values The values, either a string or an array 95 | */ 96 | public function setValues($values) 97 | { 98 | if (empty($values)) { 99 | // give it default checkbox behavior 100 | $this->_values = array('', 1); 101 | } elseif (is_scalar($values)) { 102 | // if it's string, then assume the value to 103 | // be passed is for when the element is checked 104 | $this->_values = array('', $values); 105 | } else { 106 | $this->_values = $values; 107 | } 108 | $this->updateAttributes(array('value' => $this->_values[1])); 109 | $this->setChecked($this->_currentValue == $this->_values[1]); 110 | } 111 | 112 | /** 113 | * Sets the element's value 114 | * 115 | * @param mixed Element's value 116 | */ 117 | public function setValue($value) 118 | { 119 | $this->setChecked(isset($this->_values[1]) && $value == $this->_values[1]); 120 | $this->_currentValue = $value; 121 | } 122 | 123 | /** 124 | * Returns the element's value 125 | * 126 | * @return mixed 127 | */ 128 | public function getValue() 129 | { 130 | if (is_array($this->_values)) { 131 | return $this->_values[$this->getChecked()? 1: 0]; 132 | } else { 133 | return null; 134 | } 135 | } 136 | 137 | /** 138 | * Returns the checkbox element in HTML 139 | * and the additional hidden element in HTML 140 | * 141 | * @return string 142 | */ 143 | public function toHtml() 144 | { 145 | if ($this->_flagFrozen) { 146 | return parent::toHtml(); 147 | } else { 148 | return '_getAttrString(array( 149 | 'type' => 'hidden', 150 | 'name' => $this->getName(), 151 | 'value' => $this->_values[0] 152 | )) . ' />' . parent::toHtml(); 153 | 154 | } 155 | } 156 | 157 | /** 158 | * Unlike checkbox, this has to append a hidden input in both 159 | * checked and non-checked states 160 | */ 161 | function getFrozenHtml() 162 | { 163 | return ($this->getChecked()? '[x]': '[ ]') . 164 | $this->_getPersistantData(); 165 | } 166 | 167 | /** 168 | * Called by HTML_QuickForm whenever form event is made on this element 169 | * 170 | * @param string $event Name of event 171 | * @param mixed $arg event arguments 172 | * @param object &$caller calling object 173 | */ 174 | public function onQuickFormEvent($event, $arg, &$caller) 175 | { 176 | switch ($event) { 177 | case 'updateValue': 178 | // constant values override both default and submitted ones 179 | // default values are overriden by submitted 180 | $value = $this->_findValue($caller->_constantValues); 181 | if (null === $value) { 182 | $value = $this->_findValue($caller->_submitValues); 183 | if (null === $value) { 184 | $value = $this->_findValue($caller->_defaultValues); 185 | } 186 | } 187 | if (null !== $value) { 188 | $this->setValue($value); 189 | } 190 | break; 191 | default: 192 | parent::onQuickFormEvent($event, $arg, $caller); 193 | } 194 | return true; 195 | } 196 | 197 | /** 198 | * This element has a value even if it is not checked, thus we override 199 | * checkbox's behaviour here 200 | */ 201 | public function exportValue(&$submitValues, $assoc = false) 202 | { 203 | $value = $this->_findValue($submitValues); 204 | if (null === $value) { 205 | $value = $this->getValue(); 206 | } elseif (is_array($this->_values) && ($value != $this->_values[0]) && ($value != $this->_values[1])) { 207 | $value = null; 208 | } 209 | return $this->_prepareValue($value, $assoc); 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/autocomplete.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2001-2011 The PHP Group 6 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 7 | */ 8 | 9 | /** 10 | * HTML class for an autocomplete element 11 | * 12 | * Creates an HTML input text element that 13 | * at every keypressed javascript event checks in an array of options 14 | * if there's a match and autocompletes the text in case of match. 15 | * 16 | * For the JavaScript code thanks to Martin Honnen and Nicholas C. Zakas 17 | * See {@link http://www.faqts.com/knowledge_base/view.phtml/aid/13562} and 18 | * {@link http://www.sitepoint.com/article/1220} 19 | * 20 | * Example: 21 | * 22 | * $autocomplete =& $form->addElement('autocomplete', 'fruit', 'Favourite fruit:'); 23 | * $options = array("Apple", "Orange", "Pear", "Strawberry"); 24 | * $autocomplete->setOptions($options); 25 | * 26 | * 27 | * @package HTML_QuickForm 28 | * @author Matteo Di Giovinazzo 29 | */ 30 | class HTML_QuickForm_autocomplete extends HTML_QuickForm_text 31 | { 32 | /** 33 | * Options for the autocomplete input text element 34 | * 35 | * @var array 36 | * @access private 37 | */ 38 | var $_options = array(); 39 | 40 | /** 41 | * "One-time" javascript (containing functions), see bug #4611 42 | * 43 | * @var string 44 | * @access private 45 | */ 46 | var $_js = ''; 47 | 48 | /** 49 | * Class constructor 50 | * 51 | * @param string $elementName (optional)Input field name attribute 52 | * @param string $elementLabel (optional)Input field label in form 53 | * @param array $options (optional)Autocomplete options 54 | * @param mixed $attributes (optional)Either a typical HTML attribute string 55 | * or an associative array. Date format is passed along the attributes. 56 | */ 57 | public function __construct($elementName = null, $elementLabel = null, $options = null, $attributes = null) 58 | { 59 | parent::__construct($elementName, $elementLabel, $attributes); 60 | $this->_persistantFreeze = true; 61 | $this->_type = 'autocomplete'; 62 | if (isset($options)) { 63 | $this->setOptions($options); 64 | } 65 | } 66 | 67 | /** 68 | * Sets the options for the autocomplete input text element 69 | * 70 | * @param array $options Array of options for the autocomplete input text element 71 | */ 72 | public function setOptions($options) 73 | { 74 | $this->_options = array_values($options); 75 | } 76 | 77 | /** 78 | * Returns Html for the autocomplete input text element 79 | * 80 | * @return string 81 | */ 82 | public function toHtml() 83 | { 84 | // prevent problems with grouped elements 85 | $arrayName = str_replace(array('[', ']'), array('__', ''), $this->getName()) . '_values'; 86 | 87 | $this->updateAttributes(array( 88 | 'onkeypress' => 'return window.autocomplete(this, event, ' . $arrayName . ');' 89 | )); 90 | if ($this->_flagFrozen) { 91 | $js = ''; 92 | } else { 93 | $js = ""; 213 | } 214 | return $js . parent::toHtml(); 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/button.php: -------------------------------------------------------------------------------- 1 | 5 | * @author Bertrand Mansion 6 | * @copyright 2001-2011 The PHP Group 7 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 8 | */ 9 | 10 | /** 11 | * HTML class for an elements 12 | * 13 | * @package HTML_QuickForm 14 | * @author Adam Daniel 15 | * @author Bertrand Mansion 16 | */ 17 | class HTML_QuickForm_button extends HTML_QuickForm_input 18 | { 19 | /** 20 | * Class constructor 21 | * 22 | * @param string $elementName (optional)Input field name attribute 23 | * @param string $value (optional)Input field value 24 | * @param mixed $attributes (optional)Either a typical HTML attribute string 25 | * or an associative array 26 | */ 27 | public function __construct($elementName=null, $value=null, $attributes=null) 28 | { 29 | parent::__construct($elementName, null, $attributes); 30 | $this->_persistantFreeze = false; 31 | $this->setValue($value); 32 | $this->setType('button'); 33 | } 34 | 35 | /** 36 | * Freeze the element so that only its value is returned 37 | */ 38 | public function freeze() 39 | { 40 | return false; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/checkbox.php: -------------------------------------------------------------------------------- 1 | 5 | * @author Bertrand Mansion 6 | * @author Alexey Borzov 7 | * @copyright 2001-2011 The PHP Group 8 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 9 | */ 10 | 11 | /** 12 | * HTML class for a checkbox type field 13 | * 14 | * @package HTML_QuickForm 15 | * @author Adam Daniel 16 | * @author Bertrand Mansion 17 | * @author Alexey Borzov 18 | */ 19 | class HTML_QuickForm_checkbox extends HTML_QuickForm_input 20 | { 21 | /** 22 | * Checkbox display text 23 | * 24 | * @var string 25 | * @access private 26 | */ 27 | var $_text = ''; 28 | 29 | /** 30 | * Class constructor 31 | * 32 | * @param string $elementName (optional)Input field name attribute 33 | * @param string $elementLabel (optional)Input field value 34 | * @param string $text (optional)Checkbox display text 35 | * @param mixed $attributes (optional)Either a typical HTML attribute string 36 | * or an associative array 37 | */ 38 | public function __construct($elementName=null, $elementLabel=null, $text='', $attributes=null) 39 | { 40 | parent::__construct($elementName, $elementLabel, $attributes); 41 | $this->_persistantFreeze = true; 42 | $this->_text = $text; 43 | $this->setType('checkbox'); 44 | $this->updateAttributes(array('value'=>1)); 45 | $this->_generateId(); 46 | } 47 | 48 | /** 49 | * Sets whether a checkbox is checked 50 | * 51 | * @param bool $checked Whether the field is checked or not 52 | */ 53 | public function setChecked($checked) 54 | { 55 | if (!$checked) { 56 | $this->removeAttribute('checked'); 57 | } else { 58 | $this->updateAttributes(array('checked'=>'checked')); 59 | } 60 | } 61 | 62 | /** 63 | * Returns whether a checkbox is checked 64 | * 65 | * @return bool 66 | */ 67 | public function getChecked() 68 | { 69 | return (bool)$this->getAttribute('checked'); 70 | } 71 | 72 | /** 73 | * Returns the checkbox element in HTML 74 | * 75 | * @return string 76 | */ 77 | public function toHtml() 78 | { 79 | if (0 == strlen($this->_text)) { 80 | $label = ''; 81 | } elseif ($this->_flagFrozen) { 82 | $label = $this->_text; 83 | } else { 84 | $label = ''; 85 | } 86 | return HTML_QuickForm_input::toHtml() . $label; 87 | } 88 | 89 | /** 90 | * Returns the value of field without HTML tags 91 | * 92 | * @return string 93 | */ 94 | public function getFrozenHtml() 95 | { 96 | if ($this->getChecked()) { 97 | return '[x]' . 98 | $this->_getPersistantData(); 99 | } else { 100 | return '[ ]'; 101 | } 102 | } 103 | 104 | /** 105 | * Sets the checkbox text 106 | * 107 | * @param string $text 108 | */ 109 | public function setText($text) 110 | { 111 | $this->_text = (string) $text; 112 | } 113 | 114 | /** 115 | * Returns the checkbox text 116 | * 117 | * @return string 118 | */ 119 | public function getText() 120 | { 121 | return $this->_text; 122 | } 123 | 124 | /** 125 | * Sets the value of the form element 126 | * 127 | * @param string $value Default value of the form element 128 | */ 129 | public function setValue($value) 130 | { 131 | return $this->setChecked($value); 132 | } 133 | 134 | /** 135 | * Returns the value of the form element 136 | * 137 | * @return bool 138 | */ 139 | public function getValue() 140 | { 141 | return $this->getChecked(); 142 | } 143 | 144 | /** 145 | * Called by HTML_QuickForm whenever form event is made on this element 146 | * 147 | * @param string $event Name of event 148 | * @param mixed $arg event arguments 149 | * @param object &$caller calling object 150 | */ 151 | public function onQuickFormEvent($event, $arg, &$caller) 152 | { 153 | switch ($event) { 154 | case 'updateValue': 155 | // constant values override both default and submitted ones 156 | // default values are overriden by submitted 157 | $value = $this->_findValue($caller->_constantValues); 158 | if (null === $value) { 159 | // if no boxes were checked, then there is no value in the array 160 | // yet we don't want to display default value in this case 161 | if ($caller->isSubmitted()) { 162 | $value = $this->_findValue($caller->_submitValues); 163 | } else { 164 | $value = $this->_findValue($caller->_defaultValues); 165 | } 166 | } 167 | if (null !== $value || $caller->isSubmitted()) { 168 | $this->setChecked($value); 169 | } 170 | break; 171 | case 'setGroupValue': 172 | $this->setChecked($arg); 173 | break; 174 | default: 175 | parent::onQuickFormEvent($event, $arg, $caller); 176 | } 177 | return true; 178 | } 179 | 180 | /** 181 | * Return true if the checkbox is checked, null if it is not checked (getValue() returns false) 182 | */ 183 | public function exportValue(&$submitValues, $assoc = false) 184 | { 185 | $value = $this->_findValue($submitValues); 186 | if (null === $value) { 187 | $value = $this->getChecked()? true: null; 188 | } 189 | return $this->_prepareValue($value, $assoc); 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/element.php: -------------------------------------------------------------------------------- 1 | 5 | * @author Bertrand Mansion 6 | * @author Alexey Borzov 7 | * @copyright 2001-2011 The PHP Group 8 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 9 | */ 10 | 11 | /** 12 | * Base class for form elements 13 | * 14 | * @package HTML_QuickForm 15 | * @author Adam Daniel 16 | * @author Bertrand Mansion 17 | * @author Alexey Borzov 18 | */ 19 | abstract class HTML_QuickForm_element extends HTML_Common 20 | { 21 | /** 22 | * Label of the field 23 | * 24 | * @var string 25 | * @access private 26 | */ 27 | var $_label = ''; 28 | 29 | /** 30 | * Form element type 31 | * 32 | * @var string 33 | * @access private 34 | */ 35 | var $_type = ''; 36 | 37 | /** 38 | * Flag to tell if element is frozen 39 | * 40 | * @var boolean 41 | * @access private 42 | */ 43 | var $_flagFrozen = false; 44 | 45 | /** 46 | * Does the element support persistant data when frozen 47 | * 48 | * @var boolean 49 | * @access private 50 | */ 51 | var $_persistantFreeze = false; 52 | 53 | /** 54 | * Class constructor 55 | * 56 | * @param string Name of the element 57 | * @param mixed Label(s) for the element 58 | * @param mixed Associative array of tag attributes or HTML attributes name="value" pairs 59 | */ 60 | public function __construct($elementName=null, $elementLabel=null, $attributes=null) 61 | { 62 | parent::__construct($attributes); 63 | if (isset($elementName)) { 64 | $this->setName($elementName); 65 | } 66 | if (isset($elementLabel)) { 67 | $this->setLabel($elementLabel); 68 | } 69 | } 70 | 71 | /** 72 | * Returns the current API version 73 | * 74 | * @return float 75 | */ 76 | public function apiVersion() 77 | { 78 | return 3.2; 79 | } 80 | 81 | /** 82 | * Returns element type 83 | * 84 | * @return string 85 | */ 86 | public function getType() 87 | { 88 | return $this->_type; 89 | } 90 | 91 | /** 92 | * Sets the input field name 93 | * 94 | * @param string $name Input field name attribute 95 | */ 96 | public function setName($name) 97 | { 98 | // interface method 99 | } 100 | 101 | /** 102 | * Returns the element name 103 | * 104 | * @return string 105 | */ 106 | public function getName() 107 | { 108 | // interface method 109 | } 110 | 111 | /** 112 | * Sets the value of the form element 113 | * 114 | * @param string $value Default value of the form element 115 | */ 116 | public function setValue($value) 117 | { 118 | // interface 119 | } 120 | 121 | /** 122 | * Returns the value of the form element 123 | * 124 | * @return mixed 125 | */ 126 | public function getValue() 127 | { 128 | // interface 129 | return null; 130 | } 131 | 132 | /** 133 | * Freeze the element so that only its value is returned 134 | */ 135 | public function freeze() 136 | { 137 | $this->_flagFrozen = true; 138 | } 139 | 140 | /** 141 | * Unfreezes the element so that it becomes editable 142 | */ 143 | public function unfreeze() 144 | { 145 | $this->_flagFrozen = false; 146 | } 147 | 148 | /** 149 | * Returns the value of field without HTML tags 150 | * 151 | * @return string 152 | */ 153 | public function getFrozenHtml() 154 | { 155 | $value = $this->getValue(); 156 | return (strlen((string) $value)? htmlspecialchars($value): ' ') . 157 | $this->_getPersistantData(); 158 | } 159 | 160 | /** 161 | * Used by getFrozenHtml() to pass the element's value if _persistantFreeze is on 162 | * 163 | * @access private 164 | * @return string 165 | */ 166 | function _getPersistantData() 167 | { 168 | if (!$this->_persistantFreeze) { 169 | return ''; 170 | } else { 171 | $id = $this->getAttribute('id'); 172 | return '_getAttrString(array( 173 | 'type' => 'hidden', 174 | 'name' => $this->getName(), 175 | 'value' => $this->getValue() 176 | ) + (isset($id)? array('id' => $id): array())) . ' />'; 177 | } 178 | } 179 | 180 | /** 181 | * Returns whether or not the element is frozen 182 | * 183 | * @return bool 184 | */ 185 | public function isFrozen() 186 | { 187 | return $this->_flagFrozen; 188 | } 189 | 190 | /** 191 | * Sets wether an element value should be kept in an hidden field 192 | * when the element is frozen or not 193 | * 194 | * @param bool $persistant True if persistant value 195 | */ 196 | public function setPersistantFreeze($persistant=false) 197 | { 198 | $this->_persistantFreeze = $persistant; 199 | } 200 | 201 | /** 202 | * Sets display text for the element 203 | * 204 | * @param string $label Display text for the element 205 | */ 206 | public function setLabel($label) 207 | { 208 | $this->_label = $label; 209 | } 210 | 211 | /** 212 | * Returns display text for the element 213 | * 214 | * @return string 215 | */ 216 | public function getLabel() 217 | { 218 | return $this->_label; 219 | } 220 | 221 | /** 222 | * Tries to find the element value from the values array 223 | * 224 | * @return mixed 225 | */ 226 | protected function _findValue(&$values) 227 | { 228 | if (empty($values)) { 229 | return null; 230 | } 231 | $elementName = (string) $this->getName(); 232 | if (isset($values[$elementName])) { 233 | return $values[$elementName]; 234 | } elseif (strpos($elementName, '[')) { 235 | $keys = str_replace( 236 | array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"), 237 | $elementName 238 | ); 239 | $arrayKeys = explode("']['", $keys); 240 | return HTML_QuickForm_utils::recursiveValue($values, $arrayKeys); 241 | } 242 | return null; 243 | } 244 | 245 | /** 246 | * Called by HTML_QuickForm whenever form event is made on this element 247 | * 248 | * @param string $event Name of event 249 | * @param mixed $arg event arguments 250 | * @param object &$caller calling object 251 | */ 252 | public function onQuickFormEvent($event, $arg, &$caller) 253 | { 254 | switch ($event) { 255 | case 'createElement': 256 | break; 257 | case 'addElement': 258 | $this->onQuickFormEvent('updateValue', null, $caller); 259 | break; 260 | case 'updateValue': 261 | // constant values override both default and submitted ones 262 | // default values are overriden by submitted 263 | $value = $this->_findValue($caller->_constantValues); 264 | if (null === $value) { 265 | $value = $this->_findValue($caller->_submitValues); 266 | if (null === $value) { 267 | $value = $this->_findValue($caller->_defaultValues); 268 | } 269 | } 270 | if (null !== $value) { 271 | $this->setValue($value); 272 | } 273 | break; 274 | case 'setGroupValue': 275 | $this->setValue($arg); 276 | } 277 | return true; 278 | } 279 | 280 | /** 281 | * Accepts a renderer 282 | * 283 | * @param HTML_QuickForm_Renderer renderer object 284 | * @param boolean Whether an element is required 285 | * @param string An error message associated with an element 286 | */ 287 | public function accept(HTML_QuickForm_Renderer &$renderer, $required = false, $error = null) 288 | { 289 | $renderer->renderElement($this, $required, $error); 290 | } 291 | 292 | /** 293 | * Automatically generates and assigns an 'id' attribute for the element. 294 | * 295 | * Currently used to ensure that labels work on radio buttons and 296 | * checkboxes. Per idea of Alexander Radivanovich. 297 | * 298 | * @access private 299 | */ 300 | function _generateId() 301 | { 302 | static $idx = 1; 303 | 304 | if (!$this->getAttribute('id')) { 305 | $this->updateAttributes(array('id' => 'qf_' . substr(md5(microtime() . $idx++), 0, 6))); 306 | } 307 | } 308 | 309 | /** 310 | * Returns a 'safe' element's value 311 | * 312 | * @param array array of submitted values to search 313 | * @param bool whether to return the value as associative array 314 | * @return mixed 315 | */ 316 | public function exportValue(&$submitValues, $assoc = false) 317 | { 318 | $value = $this->_findValue($submitValues); 319 | if (null === $value) { 320 | $value = $this->getValue(); 321 | } 322 | return $this->_prepareValue($value, $assoc); 323 | } 324 | 325 | /** 326 | * Used by exportValue() to prepare the value for returning 327 | * 328 | * @param mixed the value found in exportValue() 329 | * @param bool whether to return the value as associative array 330 | * @access private 331 | * @return mixed 332 | */ 333 | function _prepareValue($value, $assoc) 334 | { 335 | if (null === $value) { 336 | return null; 337 | } elseif (!$assoc) { 338 | return $value; 339 | } else { 340 | $name = $this->getName(); 341 | if (!strpos($name, '[')) { 342 | return array($name => $value); 343 | } else { 344 | $keys = str_replace( 345 | array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"), 346 | $name 347 | ); 348 | $keysArray = explode("']['", $keys); 349 | return HTML_QuickForm_utils::recursiveBuild($keysArray, $value); 350 | } 351 | } 352 | } 353 | } 354 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/file.php: -------------------------------------------------------------------------------- 1 | 5 | * @author Bertrand Mansion 6 | * @author Alexey Borzov 7 | * @copyright 2001-2011 The PHP Group 8 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 9 | */ 10 | 11 | /** 12 | * HTML class for a file upload field 13 | * 14 | * @package HTML_QuickForm 15 | * @author Adam Daniel 16 | * @author Bertrand Mansion 17 | * @author Alexey Borzov 18 | */ 19 | class HTML_QuickForm_file extends HTML_QuickForm_input 20 | { 21 | /** 22 | * Uploaded file data, from $_FILES 23 | * @var array 24 | */ 25 | var $_value = null; 26 | 27 | /** 28 | * Class constructor 29 | * 30 | * @param string Input field name attribute 31 | * @param string Input field label 32 | * @param mixed (optional)Either a typical HTML attribute string 33 | * or an associative array 34 | */ 35 | public function __construct($elementName=null, $elementLabel=null, $attributes=null) 36 | { 37 | // register file-related rules 38 | $registry =& HTML_QuickForm_RuleRegistry::singleton(); 39 | $registry->registerRule('uploadedfile', 'callback', '_ruleIsUploadedFile', $this); 40 | $registry->registerRule('maxfilesize', 'callback', '_ruleCheckMaxFileSize', $this); 41 | $registry->registerRule('mimetype', 'callback', '_ruleCheckMimeType', $this); 42 | $registry->registerRule('filename', 'callback', '_ruleCheckFileName', $this); 43 | 44 | parent::__construct($elementName, $elementLabel, $attributes); 45 | $this->setType('file'); 46 | } 47 | 48 | /** 49 | * Sets size of file element 50 | * 51 | * @param int Size of file element 52 | */ 53 | public function setSize($size) 54 | { 55 | $this->updateAttributes(array('size' => $size)); 56 | } 57 | 58 | /** 59 | * Returns size of file element 60 | * 61 | * @return int 62 | */ 63 | public function getSize() 64 | { 65 | return $this->getAttribute('size'); 66 | } 67 | 68 | /** 69 | * Freeze the element so that only its value is returned 70 | * 71 | * @return bool 72 | */ 73 | public function freeze() 74 | { 75 | return false; 76 | } 77 | 78 | /** 79 | * Sets value for file element. 80 | * 81 | * Actually this does nothing. The function is defined here to override 82 | * HTML_Quickform_input's behaviour of setting the 'value' attribute. As 83 | * no sane user-agent uses 's value for anything 84 | * (because of security implications) we implement file's value as a 85 | * read-only property with a special meaning. 86 | * 87 | * @param mixed Value for file element 88 | */ 89 | public function setValue($value) 90 | { 91 | return null; 92 | } 93 | 94 | /** 95 | * Returns information about the uploaded file 96 | * 97 | * @return array 98 | */ 99 | public function getValue() 100 | { 101 | return $this->_value; 102 | } 103 | 104 | /** 105 | * Called by HTML_QuickForm whenever form event is made on this element 106 | * 107 | * @param string Name of event 108 | * @param mixed event arguments 109 | * @param object calling object 110 | * @return bool 111 | */ 112 | public function onQuickFormEvent($event, $arg, &$caller) 113 | { 114 | switch ($event) { 115 | case 'updateValue': 116 | if ($caller->getAttribute('method') == 'get') { 117 | throw new HTML_QuickForm_Error('Cannot add a file upload field to a GET method form'); 118 | } 119 | $this->_value = $this->_findValue($_FILES); 120 | $caller->updateAttributes(array('enctype' => 'multipart/form-data')); 121 | $caller->setMaxFileSize(); 122 | break; 123 | case 'addElement': 124 | $this->onQuickFormEvent('createElement', $arg, $caller); 125 | return $this->onQuickFormEvent('updateValue', null, $caller); 126 | break; 127 | case 'createElement': 128 | break; 129 | } 130 | return true; 131 | } 132 | 133 | /** 134 | * Moves an uploaded file into the destination 135 | * 136 | * @param string Destination directory path 137 | * @param string New file name 138 | * @return bool Whether the file was moved successfully 139 | */ 140 | public function moveUploadedFile($dest, $fileName = '') 141 | { 142 | if ($dest != '' && substr($dest, -1) != '/') { 143 | $dest .= '/'; 144 | } 145 | $fileName = ($fileName != '') ? $fileName : basename($this->_value['name']); 146 | return move_uploaded_file($this->_value['tmp_name'], $dest . $fileName); 147 | } 148 | 149 | /** 150 | * Checks if the element contains an uploaded file 151 | * 152 | * @return bool true if file has been uploaded, false otherwise 153 | */ 154 | public function isUploadedFile() 155 | { 156 | return $this->_ruleIsUploadedFile($this->_value); 157 | } 158 | 159 | /** 160 | * Checks if the given element contains an uploaded file 161 | * 162 | * @param array Uploaded file info (from $_FILES) 163 | * @access private 164 | * @return bool true if file has been uploaded, false otherwise 165 | */ 166 | function _ruleIsUploadedFile($elementValue) 167 | { 168 | if ((isset($elementValue['error']) && $elementValue['error'] == 0) || 169 | (!empty($elementValue['tmp_name']) && $elementValue['tmp_name'] != 'none')) { 170 | return is_uploaded_file($elementValue['tmp_name']); 171 | } else { 172 | return false; 173 | } 174 | } 175 | 176 | /** 177 | * Checks that the file does not exceed the max file size 178 | * 179 | * @param array Uploaded file info (from $_FILES) 180 | * @param int Max file size 181 | * @access private 182 | * @return bool true if filesize is lower than maxsize, false otherwise 183 | */ 184 | function _ruleCheckMaxFileSize($elementValue, $maxSize) 185 | { 186 | if (!empty($elementValue['error']) && 187 | (UPLOAD_ERR_FORM_SIZE == $elementValue['error'] || UPLOAD_ERR_INI_SIZE == $elementValue['error'])) { 188 | return false; 189 | } 190 | if (!$this->_ruleIsUploadedFile($elementValue)) { 191 | return true; 192 | } 193 | return ($maxSize >= @filesize($elementValue['tmp_name'])); 194 | } 195 | 196 | /** 197 | * Checks if the given element contains an uploaded file of the right mime type 198 | * 199 | * @param array Uploaded file info (from $_FILES) 200 | * @param mixed Mime Type (can be an array of allowed types) 201 | * @access private 202 | * @return bool true if mimetype is correct, false otherwise 203 | */ 204 | function _ruleCheckMimeType($elementValue, $mimeType) 205 | { 206 | if (!$this->_ruleIsUploadedFile($elementValue)) { 207 | return true; 208 | } 209 | if (is_array($mimeType)) { 210 | return in_array($elementValue['type'], $mimeType); 211 | } 212 | return $elementValue['type'] == $mimeType; 213 | } 214 | 215 | /** 216 | * Checks if the given element contains an uploaded file of the filename regex 217 | * 218 | * @param array Uploaded file info (from $_FILES) 219 | * @param string Regular expression 220 | * @access private 221 | * @return bool true if name matches regex, false otherwise 222 | */ 223 | function _ruleCheckFileName($elementValue, $regex) 224 | { 225 | if (!$this->_ruleIsUploadedFile($elementValue)) { 226 | return true; 227 | } 228 | return (bool)preg_match($regex, $elementValue['name']); 229 | } 230 | 231 | /** 232 | * Tries to find the element value from the values array 233 | * 234 | * Needs to be redefined here as $_FILES is populated differently from 235 | * other arrays when element name is of the form foo[bar] 236 | * 237 | * @return mixed 238 | */ 239 | protected function _findValue(&$values) 240 | { 241 | if (empty($values)) { 242 | return null; 243 | } 244 | $elementName = $this->getName(); 245 | if (isset($values[$elementName])) { 246 | return $values[$elementName]; 247 | } elseif (false !== ($pos = strpos($elementName, '['))) { 248 | $base = str_replace( 249 | array('\\', '\''), array('\\\\', '\\\''), 250 | substr($elementName, 0, $pos) 251 | ); 252 | $keys = str_replace( 253 | array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"), 254 | substr($elementName, $pos + 1, -1) 255 | ); 256 | $keysArray = explode("']['", $keys); 257 | 258 | if (!HTML_QuickForm_utils::recursiveIsset($values[$base]['name'], $keysArray)) { 259 | return null; 260 | } 261 | $props = array('name', 'type', 'size', 'tmp_name', 'error'); 262 | $value = array(); 263 | foreach ($props as $prop) { 264 | $value[$prop] = HTML_QuickForm_utils::recursiveValue($values[$base][$prop], $keysArray); 265 | } 266 | return $value; 267 | } else { 268 | return null; 269 | } 270 | } 271 | } 272 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/header.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2001-2011 The PHP Group 6 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 7 | */ 8 | 9 | /** 10 | * A pseudo-element used for adding headers to form 11 | * 12 | * @package HTML_QuickForm 13 | * @author Alexey Borzov 14 | */ 15 | class HTML_QuickForm_header extends HTML_QuickForm_static 16 | { 17 | /** 18 | * Class constructor 19 | * 20 | * @param string $elementName Header name 21 | * @param string $text Header text 22 | */ 23 | public function __construct($elementName = null, $text = null) 24 | { 25 | parent::__construct($elementName, null, $text); 26 | $this->_type = 'header'; 27 | } 28 | 29 | /** 30 | * Accepts a renderer 31 | * 32 | * @param HTML_QuickForm_Renderer renderer object 33 | */ 34 | public function accept(HTML_QuickForm_Renderer &$renderer, $required = false, $error = null) 35 | { 36 | $renderer->renderHeader($this); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/hidden.php: -------------------------------------------------------------------------------- 1 | 5 | * @author Bertrand Mansion 6 | * @copyright 2001-2011 The PHP Group 7 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 8 | */ 9 | 10 | /** 11 | * HTML class for a hidden type element 12 | * 13 | * @package HTML_QuickForm 14 | * @author Adam Daniel 15 | * @author Bertrand Mansion 16 | */ 17 | class HTML_QuickForm_hidden extends HTML_QuickForm_input 18 | { 19 | /** 20 | * Class constructor 21 | * 22 | * @param string $elementName (optional)Input field name attribute 23 | * @param string $value (optional)Input field value 24 | * @param mixed $attributes (optional)Either a typical HTML attribute string 25 | * or an associative array 26 | */ 27 | public function __construct($elementName=null, $value='', $attributes=null) 28 | { 29 | parent::__construct($elementName, null, $attributes); 30 | $this->setType('hidden'); 31 | $this->setValue($value); 32 | } 33 | 34 | /** 35 | * Freeze the element so that only its value is returned 36 | */ 37 | public function freeze() 38 | { 39 | return false; 40 | } 41 | 42 | /** 43 | * Render the element as a hidden field 44 | */ 45 | public function accept(HTML_QuickForm_Renderer &$renderer, $required = false, $error = null) 46 | { 47 | $renderer->renderHidden($this, $required, $error); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/hiddenselect.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2001-2011 The PHP Group 6 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 7 | */ 8 | 9 | /** 10 | * Hidden select pseudo-element 11 | * 12 | * This class takes the same arguments as a select element, but instead 13 | * of creating a select ring it creates hidden elements for all values 14 | * already selected with setDefault or setConstant. This is useful if 15 | * you have a select ring that you don't want visible, but you need all 16 | * selected values to be passed. 17 | * 18 | * @package HTML_QuickForm 19 | * @author Isaac Shepard 20 | */ 21 | class HTML_QuickForm_hiddenselect extends HTML_QuickForm_select 22 | { 23 | /** 24 | * Class constructor 25 | * 26 | * @param string Select name attribute 27 | * @param mixed Label(s) for the select (not used) 28 | * @param mixed Data to be used to populate options 29 | * @param mixed Either a typical HTML attribute string or an associative array (not used) 30 | */ 31 | public function __construct($elementName=null, $elementLabel=null, $options=null, $attributes=null) 32 | { 33 | parent::__construct($elementName, $elementLabel, $attributes); 34 | $this->_persistantFreeze = true; 35 | $this->_type = 'hiddenselect'; 36 | if (isset($options)) { 37 | $this->load($options); 38 | } 39 | } 40 | 41 | /** 42 | * Returns the SELECT in HTML 43 | * 44 | * @return string 45 | */ 46 | public function toHtml() 47 | { 48 | if (empty($this->_values)) { 49 | return ''; 50 | } 51 | 52 | $tabs = $this->_getTabs(); 53 | $name = $this->getPrivateName(); 54 | $strHtml = ''; 55 | 56 | foreach ($this->_values as $key => $val) { 57 | for ($i = 0, $optCount = count($this->_options); $i < $optCount; $i++) { 58 | if ($val == $this->_options[$i]['attr']['value']) { 59 | $strHtml .= $tabs . '_getAttrString(array( 60 | 'type' => 'hidden', 61 | 'name' => $name, 62 | 'value' => $val 63 | )) . " />\n" ; 64 | } 65 | } 66 | } 67 | 68 | return $strHtml; 69 | } 70 | 71 | /** 72 | * This is essentially a hidden element and should be rendered as one 73 | */ 74 | public function accept(HTML_QuickForm_Renderer &$renderer, $required = false, $error = null) 75 | { 76 | $renderer->renderHidden($this, $required, $error); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/html.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2001-2011 The PHP Group 6 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 7 | */ 8 | 9 | /** 10 | * A pseudo-element used for adding raw HTML to form 11 | * 12 | * Intended for use with the default renderer only, template-based 13 | * ones may (and probably will) completely ignore this 14 | * 15 | * @package HTML_QuickForm 16 | * @author Alexey Borzov 17 | * @deprecated Please use the templates rather than add raw HTML via this element 18 | */ 19 | class HTML_QuickForm_html extends HTML_QuickForm_static 20 | { 21 | /** 22 | * Class constructor 23 | * 24 | * @param string $text raw HTML to add 25 | */ 26 | function __construct($text = null) 27 | { 28 | parent::__construct(null, null, $text); 29 | $this->_type = 'html'; 30 | } 31 | 32 | /** 33 | * Accepts a renderer 34 | * 35 | * @param HTML_QuickForm_Renderer renderer object (only works with Default renderer!) 36 | */ 37 | public function accept(HTML_QuickForm_Renderer &$renderer, $required = false, $error = null) 38 | { 39 | $renderer->renderHtml($this); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/image.php: -------------------------------------------------------------------------------- 1 | 5 | * @author Bertrand Mansion 6 | * @copyright 2001-2011 The PHP Group 7 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 8 | */ 9 | 10 | /** 11 | * HTML class for an element 12 | * 13 | * @package HTML_QuickForm 14 | * @author Adam Daniel 15 | * @author Bertrand Mansion 16 | */ 17 | class HTML_QuickForm_image extends HTML_QuickForm_input 18 | { 19 | /** 20 | * Class constructor 21 | * 22 | * @param string $elementName (optional)Element name attribute 23 | * @param string $src (optional)Image source 24 | * @param mixed $attributes (optional)Either a typical HTML attribute string 25 | * or an associative array 26 | */ 27 | public function __construct($elementName=null, $src='', $attributes=null) 28 | { 29 | parent::__construct($elementName, null, $attributes); 30 | $this->setType('image'); 31 | $this->setSource($src); 32 | } 33 | 34 | /** 35 | * Sets source for image element 36 | * 37 | * @param string $src source for image element 38 | */ 39 | public function setSource($src) 40 | { 41 | $this->updateAttributes(array('src' => $src)); 42 | } 43 | 44 | /** 45 | * Sets border size for image element 46 | * 47 | * @param string $border border for image element 48 | */ 49 | public function setBorder($border) 50 | { 51 | $this->updateAttributes(array('border' => $border)); 52 | } 53 | 54 | /** 55 | * Sets alignment for image element 56 | * 57 | * @param string $align alignment for image element 58 | */ 59 | public function setAlign($align) 60 | { 61 | $this->updateAttributes(array('align' => $align)); 62 | } 63 | 64 | /** 65 | * Freeze the element so that only its value is returned 66 | */ 67 | public function freeze() 68 | { 69 | return false; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/input.php: -------------------------------------------------------------------------------- 1 | 5 | * @author Bertrand Mansion 6 | * @copyright 2001-2011 The PHP Group 7 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 8 | */ 9 | 10 | /** 11 | * Base class for form elements 12 | * 13 | * @package HTML_QuickForm 14 | * @author Adam Daniel 15 | * @author Bertrand Mansion 16 | * @abstract 17 | */ 18 | class HTML_QuickForm_input extends HTML_QuickForm_element 19 | { 20 | /** 21 | * Sets the element type 22 | * 23 | * @param string $type Element type 24 | */ 25 | public function setType($type) 26 | { 27 | $this->_type = $type; 28 | $this->updateAttributes(array('type'=>$type)); 29 | } 30 | 31 | /** 32 | * Sets the input field name 33 | * 34 | * @param string $name Input field name attribute 35 | */ 36 | public function setName($name) 37 | { 38 | $this->updateAttributes(array('name'=>$name)); 39 | } 40 | 41 | /** 42 | * Returns the element name 43 | * 44 | * @return string 45 | */ 46 | public function getName() 47 | { 48 | return $this->getAttribute('name'); 49 | } 50 | 51 | /** 52 | * Sets the value of the form element 53 | * 54 | * @param string $value Default value of the form element 55 | */ 56 | public function setValue($value) 57 | { 58 | $this->updateAttributes(array('value'=>$value)); 59 | } 60 | 61 | /** 62 | * Returns the value of the form element 63 | * 64 | * @return string 65 | */ 66 | public function getValue() 67 | { 68 | return $this->getAttribute('value'); 69 | } 70 | 71 | /** 72 | * Returns the input field in HTML 73 | * 74 | * @return string 75 | */ 76 | public function toHtml() 77 | { 78 | if ($this->_flagFrozen) { 79 | return $this->getFrozenHtml(); 80 | } else { 81 | return $this->_getTabs() . '_getAttrString($this->_attributes) . ' />'; 82 | } 83 | } 84 | 85 | /** 86 | * Called by HTML_QuickForm whenever form event is made on this element 87 | * 88 | * @param string $event Name of event 89 | * @param mixed $arg event arguments 90 | * @param object &$caller calling object 91 | */ 92 | public function onQuickFormEvent($event, $arg, &$caller) 93 | { 94 | // do not use submit values for button-type elements 95 | $type = $this->getType(); 96 | if (('updateValue' != $event) || 97 | ('submit' != $type && 'reset' != $type && 'image' != $type && 'button' != $type)) { 98 | parent::onQuickFormEvent($event, $arg, $caller); 99 | } else { 100 | $value = $this->_findValue($caller->_constantValues); 101 | if (null === $value) { 102 | $value = $this->_findValue($caller->_defaultValues); 103 | } 104 | if (null !== $value) { 105 | $this->setValue($value); 106 | } 107 | } 108 | return true; 109 | } 110 | 111 | /** 112 | * We don't need values from button-type elements (except submit) and files 113 | */ 114 | public function exportValue(&$submitValues, $assoc = false) 115 | { 116 | $type = $this->getType(); 117 | if ('reset' == $type || 'image' == $type || 'button' == $type || 'file' == $type) { 118 | return null; 119 | } else { 120 | return parent::exportValue($submitValues, $assoc); 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/link.php: -------------------------------------------------------------------------------- 1 | 5 | * @author Bertrand Mansion 6 | * @copyright 2001-2011 The PHP Group 7 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 8 | */ 9 | 10 | /** 11 | * HTML class for a link type field 12 | * 13 | * @package HTML_QuickForm 14 | * @author Adam Daniel 15 | * @author Bertrand Mansion 16 | */ 17 | class HTML_QuickForm_link extends HTML_QuickForm_static 18 | { 19 | /** 20 | * Link display text 21 | * 22 | * @var string 23 | * @access private 24 | */ 25 | var $_text = ""; 26 | 27 | /** 28 | * Class constructor 29 | * 30 | * @param string $elementLabel (optional)Link label 31 | * @param string $href (optional)Link href 32 | * @param string $text (optional)Link display text 33 | * @param mixed $attributes (optional)Either a typical HTML attribute string 34 | * or an associative array 35 | */ 36 | public function __construct($elementName=null, $elementLabel=null, $href=null, $text='', $attributes=null) 37 | { 38 | parent::__construct($elementName, $elementLabel, $attributes); 39 | $this->_persistantFreeze = false; 40 | $this->_type = 'link'; 41 | $this->setHref($href); 42 | $this->_text = $text; 43 | } 44 | 45 | /** 46 | * Sets the input field name 47 | * 48 | * @param string $name Input field name attribute 49 | */ 50 | public function setName($name) 51 | { 52 | $this->updateAttributes(array('name'=>$name)); 53 | } 54 | 55 | /** 56 | * Returns the element name 57 | * 58 | * @return string 59 | */ 60 | public function getName() 61 | { 62 | return $this->getAttribute('name'); 63 | } 64 | 65 | /** 66 | * Sets value for textarea element 67 | * 68 | * @param string $value Value for password element 69 | */ 70 | public function setValue($value) 71 | { 72 | return; 73 | } 74 | 75 | /** 76 | * Returns the value of the form element 77 | */ 78 | public function getValue() 79 | { 80 | return; 81 | } 82 | 83 | /** 84 | * Sets the links href 85 | * 86 | * @param string $href 87 | */ 88 | public function setHref($href) 89 | { 90 | $this->updateAttributes(array('href'=>$href)); 91 | } 92 | 93 | /** 94 | * Returns the textarea element in HTML 95 | * 96 | * @return string 97 | */ 98 | public function toHtml() 99 | { 100 | $tabs = $this->_getTabs(); 101 | $html = "$tabs_getAttrString($this->_attributes).">"; 102 | $html .= $this->_text; 103 | $html .= ""; 104 | return $html; 105 | } 106 | 107 | /** 108 | * Returns the value of field without HTML tags (in this case, value is changed to a mask) 109 | * 110 | * @return string 111 | */ 112 | public function getFrozenHtml() 113 | { 114 | return; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/password.php: -------------------------------------------------------------------------------- 1 | 5 | * @author Bertrand Mansion 6 | * @copyright 2001-2011 The PHP Group 7 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 8 | */ 9 | 10 | /** 11 | * HTML class for a password type field 12 | * 13 | * @package HTML_QuickForm 14 | * @author Adam Daniel 15 | * @author Bertrand Mansion 16 | */ 17 | class HTML_QuickForm_password extends HTML_QuickForm_input 18 | { 19 | /** 20 | * Class constructor 21 | * 22 | * @param string $elementName (optional)Input field name attribute 23 | * @param string $elementLabel (optional)Input field label 24 | * @param mixed $attributes (optional)Either a typical HTML attribute string 25 | * or an associative array 26 | */ 27 | public function __construct($elementName=null, $elementLabel=null, $attributes=null) 28 | { 29 | parent::__construct($elementName, $elementLabel, $attributes); 30 | $this->setType('password'); 31 | } 32 | 33 | /** 34 | * Sets size of password element 35 | * 36 | * @param string $size Size of password field 37 | */ 38 | public function setSize($size) 39 | { 40 | $this->updateAttributes(array('size'=>$size)); 41 | } 42 | 43 | /** 44 | * Sets maxlength of password element 45 | * 46 | * @param string $maxlength Maximum length of password field 47 | */ 48 | public function setMaxlength($maxlength) 49 | { 50 | $this->updateAttributes(array('maxlength'=>$maxlength)); 51 | } 52 | 53 | /** 54 | * Returns the value of field without HTML tags (in this case, value is changed to a mask) 55 | * 56 | * @return string 57 | */ 58 | public function getFrozenHtml() 59 | { 60 | $value = $this->getValue(); 61 | return ('' != $value? '**********': ' ') . 62 | $this->_getPersistantData(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/radio.php: -------------------------------------------------------------------------------- 1 | 5 | * @author Bertrand Mansion 6 | * @copyright 2001-2011 The PHP Group 7 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 8 | */ 9 | 10 | /** 11 | * HTML class for a radio type element 12 | * 13 | * @package HTML_QuickForm 14 | * @author Adam Daniel 15 | * @author Bertrand Mansion 16 | */ 17 | class HTML_QuickForm_radio extends HTML_QuickForm_input 18 | { 19 | /** 20 | * Radio display text 21 | * 22 | * @var string 23 | * @access private 24 | */ 25 | var $_text = ''; 26 | 27 | /** 28 | * Class constructor 29 | * 30 | * @param string Input field name attribute 31 | * @param mixed Label(s) for a field 32 | * @param string Text to display near the radio 33 | * @param string Input field value 34 | * @param mixed Either a typical HTML attribute string or an associative array 35 | */ 36 | public function __construct($elementName=null, $elementLabel=null, $text='', $value=null, $attributes=null) 37 | { 38 | parent::__construct($elementName, $elementLabel, $attributes); 39 | if (isset($value)) { 40 | $this->setValue($value); 41 | } 42 | $this->_persistantFreeze = true; 43 | $this->setType('radio'); 44 | $this->_text = $text; 45 | $this->_generateId(); 46 | } 47 | 48 | /** 49 | * Sets whether radio button is checked 50 | * 51 | * @param bool $checked Whether the field is checked or not 52 | */ 53 | public function setChecked($checked) 54 | { 55 | if (!$checked) { 56 | $this->removeAttribute('checked'); 57 | } else { 58 | $this->updateAttributes(array('checked'=>'checked')); 59 | } 60 | } 61 | 62 | /** 63 | * Returns whether radio button is checked 64 | * 65 | * @return string 66 | */ 67 | public function getChecked() 68 | { 69 | return $this->getAttribute('checked'); 70 | } 71 | 72 | /** 73 | * Returns the radio element in HTML 74 | * 75 | * @return string 76 | */ 77 | public function toHtml() 78 | { 79 | if (0 == strlen($this->_text)) { 80 | $label = ''; 81 | } elseif ($this->_flagFrozen) { 82 | $label = $this->_text; 83 | } else { 84 | $label = ''; 85 | } 86 | return HTML_QuickForm_input::toHtml() . $label; 87 | } 88 | 89 | /** 90 | * Returns the value of field without HTML tags 91 | * 92 | * @return string 93 | */ 94 | public function getFrozenHtml() 95 | { 96 | if ($this->getChecked()) { 97 | return '(x)' . 98 | $this->_getPersistantData(); 99 | } else { 100 | return '( )'; 101 | } 102 | } 103 | 104 | /** 105 | * Sets the radio text 106 | * 107 | * @param string $text Text to display near the radio button 108 | */ 109 | public function setText($text) 110 | { 111 | $this->_text = (string) $text; 112 | } 113 | 114 | /** 115 | * Returns the radio text 116 | * 117 | * @return string 118 | */ 119 | public function getText() 120 | { 121 | return $this->_text; 122 | } 123 | 124 | /** 125 | * Called by HTML_QuickForm whenever form event is made on this element 126 | * 127 | * @param string $event Name of event 128 | * @param mixed $arg event arguments 129 | * @param object &$caller calling object 130 | */ 131 | public function onQuickFormEvent($event, $arg, &$caller) 132 | { 133 | switch ($event) { 134 | case 'updateValue': 135 | // constant values override both default and submitted ones 136 | // default values are overriden by submitted 137 | $value = $this->_findValue($caller->_constantValues); 138 | if (null === $value) { 139 | $value = $this->_findValue($caller->_submitValues); 140 | if (null === $value) { 141 | $value = $this->_findValue($caller->_defaultValues); 142 | } 143 | } 144 | if (!is_null($value) && $value == $this->getValue()) { 145 | $this->setChecked(true); 146 | } else { 147 | $this->setChecked(false); 148 | } 149 | break; 150 | case 'setGroupValue': 151 | if ($arg == $this->getValue()) { 152 | $this->setChecked(true); 153 | } else { 154 | $this->setChecked(false); 155 | } 156 | break; 157 | default: 158 | parent::onQuickFormEvent($event, $arg, $caller); 159 | } 160 | return true; 161 | } 162 | 163 | /** 164 | * Returns the value attribute if the radio is checked, null if it is not 165 | */ 166 | public function exportValue(&$submitValues, $assoc = false) 167 | { 168 | $value = $this->_findValue($submitValues); 169 | if (null === $value) { 170 | $value = $this->getChecked()? $this->getValue(): null; 171 | } elseif ($value != $this->getValue()) { 172 | $value = null; 173 | } 174 | return $this->_prepareValue($value, $assoc); 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/reset.php: -------------------------------------------------------------------------------- 1 | 5 | * @author Bertrand Mansion 6 | * @copyright 2001-2011 The PHP Group 7 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 8 | */ 9 | 10 | /** 11 | * HTML class for a reset type element 12 | * 13 | * @package HTML_QuickForm 14 | * @author Adam Daniel 15 | * @author Bertrand Mansion 16 | */ 17 | class HTML_QuickForm_reset extends HTML_QuickForm_input 18 | { 19 | /** 20 | * Class constructor 21 | * 22 | * @param string $elementName (optional)Input field name attribute 23 | * @param string $value (optional)Input field value 24 | * @param mixed $attributes (optional)Either a typical HTML attribute string 25 | * or an associative array 26 | */ 27 | public function __construct($elementName=null, $value=null, $attributes=null) 28 | { 29 | parent::__construct($elementName, null, $attributes); 30 | $this->setValue($value); 31 | $this->setType('reset'); 32 | } 33 | 34 | /** 35 | * Freeze the element so that only its value is returned 36 | */ 37 | public function freeze() 38 | { 39 | return false; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/static.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2001-2011 The PHP Group 6 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 7 | */ 8 | 9 | /** 10 | * HTML class for static data 11 | * 12 | * @package HTML_QuickForm 13 | * @author Wojciech Gdela 14 | */ 15 | class HTML_QuickForm_static extends HTML_QuickForm_element 16 | { 17 | /** 18 | * Display text 19 | * @var string 20 | * @access private 21 | */ 22 | var $_text = ''; 23 | 24 | /** 25 | * Class constructor 26 | * 27 | * @param string $elementLabel (optional)Label 28 | * @param string $text (optional)Display text 29 | */ 30 | public function __construct($elementName=null, $elementLabel=null, $text='') 31 | { 32 | parent::__construct($elementName, $elementLabel); 33 | $this->_persistantFreeze = false; 34 | $this->_type = 'static'; 35 | $this->_text = $text; 36 | } 37 | 38 | /** 39 | * Sets the element name 40 | * 41 | * @param string $name Element name 42 | */ 43 | public function setName($name) 44 | { 45 | $this->updateAttributes(array('name'=>$name)); 46 | } 47 | 48 | /** 49 | * Returns the element name 50 | * 51 | * @return string 52 | */ 53 | public function getName() 54 | { 55 | return $this->getAttribute('name'); 56 | } 57 | 58 | /** 59 | * Sets the text 60 | * 61 | * @param string $text 62 | */ 63 | public function setText($text) 64 | { 65 | $this->_text = (string) $text; 66 | } 67 | 68 | /** 69 | * Sets the text (uses the standard setValue call to emulate a form element. 70 | * 71 | * @param string $text 72 | */ 73 | public function setValue($text) 74 | { 75 | $this->setText($text); 76 | } 77 | 78 | /** 79 | * Returns the static text element in HTML 80 | * 81 | * @return string 82 | */ 83 | public function toHtml() 84 | { 85 | return $this->_getTabs() . $this->_text; 86 | } 87 | 88 | /** 89 | * Returns the value of field without HTML tags 90 | * 91 | * @return string 92 | */ 93 | public function getFrozenHtml() 94 | { 95 | return $this->toHtml(); 96 | } 97 | 98 | /** 99 | * Called by HTML_QuickForm whenever form event is made on this element 100 | * 101 | * @param string $event Name of event 102 | * @param mixed $arg event arguments 103 | * @param object &$caller calling object 104 | */ 105 | public function onQuickFormEvent($event, $arg, &$caller) 106 | { 107 | switch ($event) { 108 | case 'updateValue': 109 | // do NOT use submitted values for static elements 110 | $value = $this->_findValue($caller->_constantValues); 111 | if (null === $value) { 112 | $value = $this->_findValue($caller->_defaultValues); 113 | } 114 | if (null !== $value) { 115 | $this->setValue($value); 116 | } 117 | break; 118 | default: 119 | parent::onQuickFormEvent($event, $arg, $caller); 120 | } 121 | return true; 122 | } 123 | 124 | /** 125 | * We override this here because we don't want any values from static elements 126 | */ 127 | public function exportValue(&$submitValues, $assoc = false) 128 | { 129 | return null; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/submit.php: -------------------------------------------------------------------------------- 1 | 5 | * @author Bertrand Mansion 6 | * @copyright 2001-2011 The PHP Group 7 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 8 | */ 9 | 10 | /** 11 | * HTML class for a submit type element 12 | * 13 | * @package HTML_QuickForm 14 | * @author Adam Daniel 15 | * @author Bertrand Mansion 16 | */ 17 | class HTML_QuickForm_submit extends HTML_QuickForm_input 18 | { 19 | /** 20 | * Class constructor 21 | * 22 | * @param string Input field name attribute 23 | * @param string Input field value 24 | * @param mixed Either a typical HTML attribute string or an associative array 25 | */ 26 | public function __construct($elementName=null, $value=null, $attributes=null) 27 | { 28 | parent::__construct($elementName, null, $attributes); 29 | $this->setValue($value); 30 | $this->setType('submit'); 31 | } 32 | 33 | /** 34 | * Freeze the element so that only its value is returned 35 | */ 36 | public function freeze() 37 | { 38 | return false; 39 | } 40 | 41 | /** 42 | * Only return the value if it is found within $submitValues (i.e. if 43 | * this particular submit button was clicked) 44 | */ 45 | public function exportValue(&$submitValues, $assoc = false) 46 | { 47 | return $this->_prepareValue($this->_findValue($submitValues), $assoc); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/text.php: -------------------------------------------------------------------------------- 1 | 5 | * @author Bertrand Mansion 6 | * @copyright 2001-2011 The PHP Group 7 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 8 | */ 9 | 10 | /** 11 | * HTML class for a text field 12 | * 13 | * @package HTML_QuickForm 14 | * @author Adam Daniel 15 | * @author Bertrand Mansion 16 | */ 17 | class HTML_QuickForm_text extends HTML_QuickForm_input 18 | { 19 | /** 20 | * Class constructor 21 | * 22 | * @param string $elementName (optional)Input field name attribute 23 | * @param string $elementLabel (optional)Input field label 24 | * @param mixed $attributes (optional)Either a typical HTML attribute string 25 | * or an associative array 26 | */ 27 | public function __construct($elementName=null, $elementLabel=null, $attributes=null) 28 | { 29 | parent::__construct($elementName, $elementLabel, $attributes); 30 | $this->_persistantFreeze = true; 31 | $this->setType('text'); 32 | } 33 | 34 | /** 35 | * Sets size of text field 36 | * 37 | * @param string $size Size of text field 38 | */ 39 | public function setSize($size) 40 | { 41 | $this->updateAttributes(array('size'=>$size)); 42 | } 43 | 44 | /** 45 | * Sets maxlength of text field 46 | * 47 | * @param string $maxlength Maximum length of text field 48 | */ 49 | public function setMaxlength($maxlength) 50 | { 51 | $this->updateAttributes(array('maxlength'=>$maxlength)); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/textarea.php: -------------------------------------------------------------------------------- 1 | 5 | * @author Bertrand Mansion 6 | * @copyright 2001-2011 The PHP Group 7 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 8 | */ 9 | 10 | /** 11 | * HTML class for a textarea type field 12 | * 13 | * @package HTML_QuickForm 14 | * @author Adam Daniel 15 | * @author Bertrand Mansion 16 | */ 17 | class HTML_QuickForm_textarea extends HTML_QuickForm_element 18 | { 19 | /** 20 | * Field value 21 | * 22 | * @var string 23 | * @access private 24 | */ 25 | var $_value = null; 26 | 27 | /** 28 | * Class constructor 29 | * 30 | * @param string Input field name attribute 31 | * @param mixed Label(s) for a field 32 | * @param mixed Either a typical HTML attribute string or an associative array 33 | */ 34 | public function __construct($elementName=null, $elementLabel=null, $attributes=null) 35 | { 36 | parent::__construct($elementName, $elementLabel, $attributes); 37 | $this->_persistantFreeze = true; 38 | $this->_type = 'textarea'; 39 | } 40 | 41 | /** 42 | * Sets the input field name 43 | * 44 | * @param string $name Input field name attribute 45 | */ 46 | public function setName($name) 47 | { 48 | $this->updateAttributes(array('name'=>$name)); 49 | } 50 | 51 | /** 52 | * Returns the element name 53 | * 54 | * @return string 55 | */ 56 | public function getName() 57 | { 58 | return $this->getAttribute('name'); 59 | } 60 | 61 | /** 62 | * Sets value for textarea element 63 | * 64 | * @param string $value Value for textarea element 65 | */ 66 | public function setValue($value) 67 | { 68 | $this->_value = $value; 69 | } 70 | 71 | /** 72 | * Returns the value of the form element 73 | * 74 | * @return string 75 | */ 76 | public function getValue() 77 | { 78 | return $this->_value; 79 | } 80 | 81 | /** 82 | * Sets wrap type for textarea element 83 | * 84 | * @param string $wrap Wrap type 85 | */ 86 | public function setWrap($wrap) 87 | { 88 | $this->updateAttributes(array('wrap' => $wrap)); 89 | } 90 | 91 | /** 92 | * Sets height in rows for textarea element 93 | * 94 | * @param string $rows Height expressed in rows 95 | */ 96 | public function setRows($rows) 97 | { 98 | $this->updateAttributes(array('rows' => $rows)); 99 | } 100 | 101 | /** 102 | * Sets width in cols for textarea element 103 | * 104 | * @param string $cols Width expressed in cols 105 | */ 106 | public function setCols($cols) 107 | { 108 | $this->updateAttributes(array('cols' => $cols)); 109 | } 110 | 111 | /** 112 | * Returns the textarea element in HTML 113 | * 114 | * @return string 115 | */ 116 | public function toHtml() 117 | { 118 | if ($this->_flagFrozen) { 119 | return $this->getFrozenHtml(); 120 | } else { 121 | return $this->_getTabs() . 122 | '_getAttrString($this->_attributes) . '>' . 123 | // because we wrap the form later we don't want the text indented 124 | preg_replace("/(\r\n|\n|\r)/", ' ', htmlspecialchars((string) $this->_value)) . 125 | ''; 126 | } 127 | } 128 | 129 | /** 130 | * Returns the value of field without HTML tags (in this case, value is changed to a mask) 131 | * 132 | * @return string 133 | */ 134 | public function getFrozenHtml() 135 | { 136 | $value = htmlspecialchars($this->getValue()); 137 | if ($this->getAttribute('wrap') == 'off') { 138 | $html = $this->_getTabs() . '
' . $value."
\n"; 139 | } else { 140 | $html = nl2br($value)."\n"; 141 | } 142 | return $html . $this->_getPersistantData(); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/utils.php: -------------------------------------------------------------------------------- 1 | 16 | * @copyright 2001-2018 The PHP Group 17 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 18 | * @version CVS: $Id$ 19 | * @link http://pear.php.net/package/HTML_QuickForm 20 | */ 21 | 22 | /** 23 | * Provides a collection of static methods for array manipulation. 24 | * 25 | * (courtesy of CiviCRM project (https://civicrm.org/) 26 | * 27 | * @category HTML 28 | * @package HTML_QuickForm 29 | * @author Chuck Burgess 30 | * @version Release: @package_version@ 31 | * @since 3.2 32 | */ 33 | class HTML_QuickForm_utils 34 | { 35 | /** 36 | * Get a single value from an array-tree. 37 | * 38 | * @param array $values Ex: ['foo' => ['bar' => 123]]. 39 | * @param array $path Ex: ['foo', 'bar']. 40 | * @param mixed $default 41 | * @return mixed Ex 123. 42 | */ 43 | public static function pathGet($values, $path, $default = NULL) { 44 | foreach ($path as $key) { 45 | if (!is_array($values) || !isset($values[$key])) { 46 | return $default; 47 | } 48 | $values = $values[$key]; 49 | } 50 | return $values; 51 | } 52 | 53 | /** 54 | * Check if a key isset which may be several layers deep. 55 | * 56 | * This is a helper for when the calling function does not know how many layers deep 57 | * the path array is so cannot easily check. 58 | * 59 | * @param array $values 60 | * @param array $path 61 | * @return bool 62 | */ 63 | public static function pathIsset($values, $path) { 64 | foreach ($path as $key) { 65 | if (!is_array($values) || !isset($values[$key])) { 66 | return FALSE; 67 | } 68 | $values = $values[$key]; 69 | } 70 | return TRUE; 71 | } 72 | 73 | /** 74 | * Set a single value in an array tree. 75 | * 76 | * @param array $values Ex: ['foo' => ['bar' => 123]]. 77 | * @param array $pathParts Ex: ['foo', 'bar']. 78 | * @param mixed $value Ex: 456. 79 | * @return void 80 | */ 81 | public static function pathSet(&$values, $pathParts, $value) { 82 | $r = &$values; 83 | $last = array_pop($pathParts); 84 | foreach ($pathParts as $part) { 85 | if (!isset($r[$part])) { 86 | $r[$part] = array(); 87 | } 88 | $r = &$r[$part]; 89 | } 90 | $r[$last] = $value; 91 | } 92 | 93 | /** 94 | * Check if a key isset which may be several layers deep. 95 | * 96 | * This is a helper for when the calling function does not know how many layers deep the 97 | * path array is so cannot easily check. 98 | * 99 | * @param array $array 100 | * @param array $path 101 | * @return bool 102 | */ 103 | public static function recursiveIsset($array, $path) { 104 | return self::pathIsset($array, $path); 105 | } 106 | 107 | /** 108 | * Check if a key isset which may be several layers deep. 109 | * 110 | * This is a helper for when the calling function does not know how many layers deep the 111 | * path array is so cannot easily check. 112 | * 113 | * @param array $array 114 | * @param array $path An array of keys, 115 | * e.g [0, 'bob', 8] where we want to check if $array[0]['bob'][8] 116 | * @param mixed $default Value to return if not found. 117 | * @return bool 118 | */ 119 | public static function recursiveValue($array, $path, $default = NULL) { 120 | return self::pathGet($array, $path, $default); 121 | } 122 | 123 | /** 124 | * Append the value to the array using the key provided. 125 | * 126 | * e.g if value is 'llama' & path is [0, 'email', 'location'] result will be 127 | * [0 => ['email' => ['location' => 'llama']] 128 | * 129 | * @param $path 130 | * @param $value 131 | * @param array $source 132 | * @return array 133 | */ 134 | public static function recursiveBuild($path, $value, $source = array()) { 135 | self::pathSet($source, $path, $value); 136 | return $source; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /lib/HTML/QuickForm/xbutton.php: -------------------------------------------------------------------------------- 1 | 5 | * @copyright 2001-2011 The PHP Group 6 | * @license http://www.php.net/license/3_01.txt PHP License 3.01 7 | */ 8 | 9 | /** 10 | * Class for HTML 4.0 tags) 29 | * @param mixed Either a typical HTML attribute string or an associative array 30 | */ 31 | public function __construct($elementName = null, $elementContent = null, $attributes = null) 32 | { 33 | parent::__construct($elementName, null, $attributes); 34 | $this->setContent($elementContent); 35 | $this->setPersistantFreeze(false); 36 | $this->_type = 'xbutton'; 37 | } 38 | 39 | function toHtml() 40 | { 41 | return 'getAttributes(true) . '>' . $this->_content . ''; 42 | } 43 | 44 | function getFrozenHtml() 45 | { 46 | return $this->toHtml(); 47 | } 48 | 49 | function freeze() 50 | { 51 | return false; 52 | } 53 | 54 | function setName($name) 55 | { 56 | $this->updateAttributes(array( 57 | 'name' => $name 58 | )); 59 | } 60 | 61 | function getName() 62 | { 63 | return $this->getAttribute('name'); 64 | } 65 | 66 | function setValue($value) 67 | { 68 | $this->updateAttributes(array( 69 | 'value' => $value 70 | )); 71 | } 72 | 73 | function getValue() 74 | { 75 | return $this->getAttribute('value'); 76 | } 77 | 78 | /** 79 | * Sets the contents of the button element 80 | * 81 | * @param string Button content (HTML to add between tags) 82 | */ 83 | function setContent($content) 84 | { 85 | $this->_content = $content; 86 | } 87 | 88 | function onQuickFormEvent($event, $arg, &$caller) 89 | { 90 | if ('updateValue' != $event) { 91 | return parent::onQuickFormEvent($event, $arg, $caller); 92 | } else { 93 | $value = $this->_findValue($caller->_constantValues); 94 | if (null === $value) { 95 | $value = $this->_findValue($caller->_defaultValues); 96 | } 97 | if (null !== $value) { 98 | $this->setValue($value); 99 | } 100 | } 101 | return true; 102 | } 103 | 104 | /** 105 | * Returns a 'safe' element's value 106 | * 107 | * The value is only returned if the button's type is "submit" and if this 108 | * particlular button was clicked 109 | */ 110 | public function exportValue(&$submitValues, $assoc = false) 111 | { 112 | if ('submit' == $this->getAttribute('type')) { 113 | return $this->_prepareValue($this->_findValue($submitValues), $assoc); 114 | } else { 115 | return null; 116 | } 117 | } 118 | } 119 | --------------------------------------------------------------------------------