1<?php 2/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 3 4/** 5 * A static renderer for HTML_QuickForm compatible 6 * with HTML_Template_IT and HTML_Template_Sigma. 7 * 8 * PHP versions 4 and 5 9 * 10 * LICENSE: This source file is subject to version 3.01 of the PHP license 11 * that is available through the world-wide-web at the following URI: 12 * http://www.php.net/license/3_01.txt If you did not receive a copy of 13 * the PHP License and are unable to obtain it through the web, please 14 * send a note to license@php.net so we can mail you a copy immediately. 15 * 16 * @category HTML 17 * @package HTML_QuickForm 18 * @author Bertrand Mansion <bmansion@mamasam.com> 19 * @copyright 2001-2011 The PHP Group 20 * @license http://www.php.net/license/3_01.txt PHP License 3.01 21 * @version CVS: $Id$ 22 * @link http://pear.php.net/package/HTML_QuickForm 23 */ 24 25/** 26 * An abstract base class for QuickForm renderers 27 */ 28require_once 'HTML/QuickForm/Renderer.php'; 29 30/** 31 * A static renderer for HTML_QuickForm compatible 32 * with HTML_Template_IT and HTML_Template_Sigma. 33 * 34 * As opposed to the dynamic renderer, this renderer needs 35 * every elements and labels in the form to be specified by 36 * placeholders at the position you want them to be displayed. 37 * 38 * @category HTML 39 * @package HTML_QuickForm 40 * @author Bertrand Mansion <bmansion@mamasam.com> 41 * @version Release: 3.2.16 42 * @since 3.0 43 */ 44class HTML_QuickForm_Renderer_ITStatic extends HTML_QuickForm_Renderer 45{ 46 /**#@+ 47 * @access private 48 */ 49 /** 50 * An HTML_Template_IT or some other API compatible Template instance 51 * @var object 52 */ 53 var $_tpl = null; 54 55 /** 56 * Rendered form name 57 * @var string 58 */ 59 var $_formName = 'form'; 60 61 /** 62 * The errors that were not shown near concrete fields go here 63 * @var array 64 */ 65 var $_errors = array(); 66 67 /** 68 * Show the block with required note? 69 * @var bool 70 */ 71 var $_showRequired = false; 72 73 /** 74 * Which group are we currently parsing ? 75 * @var string 76 */ 77 var $_inGroup; 78 79 /** 80 * Index of the element in its group 81 * @var int 82 */ 83 var $_elementIndex = 0; 84 85 /** 86 * If elements have been added with the same name 87 * @var array 88 */ 89 var $_duplicateElements = array(); 90 91 /** 92 * How to handle the required tag for required fields 93 * @var string 94 */ 95 var $_required = '{label}<font size="1" color="red">*</font>'; 96 97 /** 98 * How to handle error messages in form validation 99 * @var string 100 */ 101 var $_error = '<font color="red">{error}</font><br />{html}'; 102 103 /** 104 * Collected HTML for hidden elements, if needed 105 * @var string 106 */ 107 var $_hidden = ''; 108 /**#@-*/ 109 110 /** 111 * Constructor 112 * 113 * @param HTML_Template_IT|HTML_Template_Sigma Template object to use 114 */ 115 function HTML_QuickForm_Renderer_ITStatic(&$tpl) 116 { 117 $this->HTML_QuickForm_Renderer(); 118 $this->_tpl =& $tpl; 119 } // end constructor 120 121 /** 122 * Called when visiting a form, before processing any form elements 123 * 124 * @param HTML_QuickForm form object being visited 125 * @access public 126 * @return void 127 */ 128 function startForm(&$form) 129 { 130 $this->_formName = $form->getAttribute('id'); 131 132 if (count($form->_duplicateIndex) > 0) { 133 // Take care of duplicate elements 134 foreach ($form->_duplicateIndex as $elementName => $indexes) { 135 $this->_duplicateElements[$elementName] = 0; 136 } 137 } 138 } // end func startForm 139 140 /** 141 * Called when visiting a form, after processing all form elements 142 * 143 * @param HTML_QuickForm form object being visited 144 * @access public 145 * @return void 146 */ 147 function finishForm(&$form) 148 { 149 // display errors above form 150 if (!empty($this->_errors) && $this->_tpl->blockExists($this->_formName.'_error_loop')) { 151 foreach ($this->_errors as $error) { 152 $this->_tpl->setVariable($this->_formName.'_error', $error); 153 $this->_tpl->parse($this->_formName.'_error_loop'); 154 } 155 } 156 // show required note 157 if ($this->_showRequired) { 158 $this->_tpl->setVariable($this->_formName.'_required_note', $form->getRequiredNote()); 159 } 160 // add hidden elements, if collected 161 if (!empty($this->_hidden)) { 162 $this->_tpl->setVariable($this->_formName . '_hidden', $this->_hidden); 163 } 164 // assign form attributes 165 $this->_tpl->setVariable($this->_formName.'_attributes', $form->getAttributes(true)); 166 // assign javascript validation rules 167 $this->_tpl->setVariable($this->_formName.'_javascript', $form->getValidationScript()); 168 } // end func finishForm 169 170 /** 171 * Called when visiting a header element 172 * 173 * @param HTML_QuickForm_header header element being visited 174 * @access public 175 * @return void 176 */ 177 function renderHeader(&$header) 178 { 179 $name = $header->getName(); 180 $varName = $this->_formName.'_header'; 181 182 // Find placeHolder 183 if (!empty($name) && $this->_tpl->placeHolderExists($this->_formName.'_header_'.$name)) { 184 $varName = $this->_formName.'_header_'.$name; 185 } 186 $this->_tpl->setVariable($varName, $header->toHtml()); 187 } // end func renderHeader 188 189 /** 190 * Called when visiting an element 191 * 192 * @param HTML_QuickForm_element form element being visited 193 * @param bool Whether an element is required 194 * @param string An error message associated with an element 195 * @access public 196 * @return void 197 */ 198 function renderElement(&$element, $required, $error) 199 { 200 $name = $element->getName(); 201 202 // are we inside a group? 203 if (!empty($this->_inGroup)) { 204 $varName = $this->_formName.'_'.str_replace(array('[', ']'), '_', $name); 205 if (substr($varName, -2) == '__') { 206 // element name is of type : group[] 207 $varName = $this->_inGroup.'_'.$this->_elementIndex.'_'; 208 $this->_elementIndex++; 209 } 210 if ($varName != $this->_inGroup) { 211 $varName .= '_' == substr($varName, -1)? '': '_'; 212 // element name is of type : group[name] 213 $label = $element->getLabel(); 214 $html = $element->toHtml(); 215 216 if ($required && !$element->isFrozen()) { 217 $this->_renderRequired($label, $html); 218 $this->_showRequired = true; 219 } 220 if (!empty($label)) { 221 if (is_array($label)) { 222 foreach ($label as $key => $value) { 223 $this->_tpl->setVariable($varName.'label_'.$key, $value); 224 } 225 } else { 226 $this->_tpl->setVariable($varName.'label', $label); 227 } 228 } 229 $this->_tpl->setVariable($varName.'html', $html); 230 } 231 232 } else { 233 234 $name = str_replace(array('[', ']'), array('_', ''), $name); 235 236 if (isset($this->_duplicateElements[$name])) { 237 // Element is a duplicate 238 $varName = $this->_formName.'_'.$name.'_'.$this->_duplicateElements[$name]; 239 $this->_duplicateElements[$name]++; 240 } else { 241 $varName = $this->_formName.'_'.$name; 242 } 243 244 $label = $element->getLabel(); 245 $html = $element->toHtml(); 246 247 if ($required) { 248 $this->_showRequired = true; 249 $this->_renderRequired($label, $html); 250 } 251 if (!empty($error)) { 252 $this->_renderError($label, $html, $error); 253 } 254 if (is_array($label)) { 255 foreach ($label as $key => $value) { 256 $this->_tpl->setVariable($varName.'_label_'.$key, $value); 257 } 258 } else { 259 $this->_tpl->setVariable($varName.'_label', $label); 260 } 261 $this->_tpl->setVariable($varName.'_html', $html); 262 } 263 } // end func renderElement 264 265 /** 266 * Called when visiting a hidden element 267 * 268 * @param HTML_QuickForm_element hidden element being visited 269 * @access public 270 * @return void 271 */ 272 function renderHidden(&$element) 273 { 274 if ($this->_tpl->placeholderExists($this->_formName . '_hidden')) { 275 $this->_hidden .= $element->toHtml(); 276 } else { 277 $name = $element->getName(); 278 $name = str_replace(array('[', ']'), array('_', ''), $name); 279 $this->_tpl->setVariable($this->_formName.'_'.$name.'_html', $element->toHtml()); 280 } 281 } // end func renderHidden 282 283 /** 284 * Called when visiting a group, before processing any group elements 285 * 286 * @param HTML_QuickForm_group group being visited 287 * @param bool Whether a group is required 288 * @param string An error message associated with a group 289 * @access public 290 * @return void 291 */ 292 function startGroup(&$group, $required, $error) 293 { 294 $name = $group->getName(); 295 $varName = $this->_formName.'_'.$name; 296 297 $this->_elementIndex = 0; 298 299 $html = $this->_tpl->placeholderExists($varName.'_html') ? $group->toHtml() : ''; 300 $label = $group->getLabel(); 301 302 if ($required) { 303 $this->_renderRequired($label, $html); 304 } 305 if (!empty($error)) { 306 $this->_renderError($label, $html, $error); 307 } 308 if (!empty($html)) { 309 $this->_tpl->setVariable($varName.'_html', $html); 310 } else { 311 // Uses error blocks to set the special groups layout error 312 // <!-- BEGIN form_group_error -->{form_group_error}<!-- END form_group_error --> 313 if (!empty($error)) { 314 if ($this->_tpl->placeholderExists($varName.'_error')) { 315 if ($this->_tpl->blockExists($this->_formName . '_error_block')) { 316 $this->_tpl->setVariable($this->_formName . '_error', $error); 317 $error = $this->_getTplBlock($this->_formName . '_error_block'); 318 } elseif (strpos($this->_error, '{html}') !== false || strpos($this->_error, '{label}') !== false) { 319 $error = str_replace('{error}', $error, $this->_error); 320 } 321 } 322 $this->_tpl->setVariable($varName . '_error', $error); 323 array_pop($this->_errors); 324 } 325 } 326 if (is_array($label)) { 327 foreach ($label as $key => $value) { 328 $this->_tpl->setVariable($varName.'_label_'.$key, $value); 329 } 330 } else { 331 $this->_tpl->setVariable($varName.'_label', $label); 332 } 333 $this->_inGroup = $varName; 334 } // end func startGroup 335 336 /** 337 * Called when visiting a group, after processing all group elements 338 * 339 * @param HTML_QuickForm_group group being visited 340 * @access public 341 * @return void 342 */ 343 function finishGroup(&$group) 344 { 345 $this->_inGroup = ''; 346 } // end func finishGroup 347 348 /** 349 * Sets the way required elements are rendered 350 * 351 * You can use {label} or {html} placeholders to let the renderer know where 352 * where the element label or the element html are positionned according to the 353 * required tag. They will be replaced accordingly with the right value. 354 * For example: 355 * <font color="red">*</font>{label} 356 * will put a red star in front of the label if the element is required. 357 * 358 * @param string The required element template 359 * @access public 360 * @return void 361 */ 362 function setRequiredTemplate($template) 363 { 364 $this->_required = $template; 365 } // end func setRequiredTemplate 366 367 /** 368 * Sets the way elements with validation errors are rendered 369 * 370 * You can use {label} or {html} placeholders to let the renderer know where 371 * where the element label or the element html are positionned according to the 372 * error message. They will be replaced accordingly with the right value. 373 * The error message will replace the {error} place holder. 374 * For example: 375 * <font color="red">{error}</font><br />{html} 376 * will put the error message in red on top of the element html. 377 * 378 * If you want all error messages to be output in the main error block, do not specify 379 * {html} nor {label}. 380 * 381 * Groups can have special layouts. With this kind of groups, the renderer will need 382 * to know where to place the error message. In this case, use error blocks like: 383 * <!-- BEGIN form_group_error -->{form_group_error}<!-- END form_group_error --> 384 * where you want the error message to appear in the form. 385 * 386 * @param string The element error template 387 * @access public 388 * @return void 389 */ 390 function setErrorTemplate($template) 391 { 392 $this->_error = $template; 393 } // end func setErrorTemplate 394 395 /** 396 * Called when an element is required 397 * 398 * This method will add the required tag to the element label and/or the element html 399 * such as defined with the method setRequiredTemplate 400 * 401 * @param string The element label 402 * @param string The element html rendering 403 * @see setRequiredTemplate() 404 * @access private 405 * @return void 406 */ 407 function _renderRequired(&$label, &$html) 408 { 409 if ($this->_tpl->blockExists($tplBlock = $this->_formName . '_required_block')) { 410 if (!empty($label) && $this->_tpl->placeholderExists($this->_formName . '_label', $tplBlock)) { 411 $this->_tpl->setVariable($this->_formName . '_label', is_array($label)? $label[0]: $label); 412 if (is_array($label)) { 413 $label[0] = $this->_getTplBlock($tplBlock); 414 } else { 415 $label = $this->_getTplBlock($tplBlock); 416 } 417 } 418 if (!empty($html) && $this->_tpl->placeholderExists($this->_formName . '_html', $tplBlock)) { 419 $this->_tpl->setVariable($this->_formName . '_html', $html); 420 $html = $this->_getTplBlock($tplBlock); 421 } 422 } else { 423 if (!empty($label) && strpos($this->_required, '{label}') !== false) { 424 if (is_array($label)) { 425 $label[0] = str_replace('{label}', $label[0], $this->_required); 426 } else { 427 $label = str_replace('{label}', $label, $this->_required); 428 } 429 } 430 if (!empty($html) && strpos($this->_required, '{html}') !== false) { 431 $html = str_replace('{html}', $html, $this->_required); 432 } 433 } 434 } // end func _renderRequired 435 436 /** 437 * Called when an element has a validation error 438 * 439 * This method will add the error message to the element label or the element html 440 * such as defined with the method setErrorTemplate. If the error placeholder is not found 441 * in the template, the error will be displayed in the form error block. 442 * 443 * @param string The element label 444 * @param string The element html rendering 445 * @param string The element error 446 * @see setErrorTemplate() 447 * @access private 448 * @return void 449 */ 450 function _renderError(&$label, &$html, $error) 451 { 452 if ($this->_tpl->blockExists($tplBlock = $this->_formName . '_error_block')) { 453 $this->_tpl->setVariable($this->_formName . '_error', $error); 454 if (!empty($label) && $this->_tpl->placeholderExists($this->_formName . '_label', $tplBlock)) { 455 $this->_tpl->setVariable($this->_formName . '_label', is_array($label)? $label[0]: $label); 456 if (is_array($label)) { 457 $label[0] = $this->_getTplBlock($tplBlock); 458 } else { 459 $label = $this->_getTplBlock($tplBlock); 460 } 461 } elseif (!empty($html) && $this->_tpl->placeholderExists($this->_formName . '_html', $tplBlock)) { 462 $this->_tpl->setVariable($this->_formName . '_html', $html); 463 $html = $this->_getTplBlock($tplBlock); 464 } 465 // clean up after ourselves 466 $this->_tpl->setVariable($this->_formName . '_error', null); 467 } elseif (!empty($label) && strpos($this->_error, '{label}') !== false) { 468 if (is_array($label)) { 469 $label[0] = str_replace(array('{label}', '{error}'), array($label[0], $error), $this->_error); 470 } else { 471 $label = str_replace(array('{label}', '{error}'), array($label, $error), $this->_error); 472 } 473 } elseif (!empty($html) && strpos($this->_error, '{html}') !== false) { 474 $html = str_replace(array('{html}', '{error}'), array($html, $error), $this->_error); 475 } else { 476 $this->_errors[] = $error; 477 } 478 }// end func _renderError 479 480 481 /** 482 * Returns the block's contents 483 * 484 * The method is needed because ITX and Sigma implement clearing 485 * the block contents on get() a bit differently 486 * 487 * @param string Block name 488 * @return string Block contents 489 */ 490 function _getTplBlock($block) 491 { 492 $this->_tpl->parse($block); 493 if (is_a($this->_tpl, 'html_template_sigma')) { 494 $ret = $this->_tpl->get($block, true); 495 } else { 496 $oldClear = $this->_tpl->clearCache; 497 $this->_tpl->clearCache = true; 498 $ret = $this->_tpl->get($block); 499 $this->_tpl->clearCache = $oldClear; 500 } 501 return $ret; 502 } 503} // end class HTML_QuickForm_Renderer_ITStatic 504?>