ITStatic.php 18 KB

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