ITDynamic.php 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  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: Alexey Borzov <borz_off@cs.msu.su> |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: ITDynamic.php 6184 2005-09-07 10:08:17Z bmol $
  20. require_once 'HTML/QuickForm/Renderer.php';
  21. /**
  22. * A concrete renderer for HTML_QuickForm, using Integrated Templates.
  23. *
  24. * This is a "dynamic" renderer, which means that concrete form look
  25. * is defined at runtime. This also means that you can define
  26. * <b>one</b> template file for <b>all</b> your forms. That template
  27. * should contain a block for every element 'look' appearing in your
  28. * forms and also some special blocks (consult the examples). If a
  29. * special block is not set for an element, the renderer falls back to
  30. * a default one.
  31. *
  32. * @author Alexey Borzov <borz_off@cs.msu.su>
  33. * @access public
  34. */
  35. class HTML_QuickForm_Renderer_ITDynamic extends HTML_QuickForm_Renderer
  36. {
  37. /**
  38. * A template class (HTML_Template_ITX or HTML_Template_Sigma) instance
  39. * @var object
  40. */
  41. var $_tpl = null;
  42. /**
  43. * The errors that were not shown near concrete fields go here
  44. * @var array
  45. */
  46. var $_errors = array();
  47. /**
  48. * Show the block with required note?
  49. * @var bool
  50. */
  51. var $_showRequired = false;
  52. /**
  53. * A separator for group elements
  54. * @var mixed
  55. */
  56. var $_groupSeparator = null;
  57. /**
  58. * The current element index inside a group
  59. * @var integer
  60. */
  61. var $_groupElementIdx = 0;
  62. /**
  63. * Blocks to use for different elements
  64. * @var array
  65. */
  66. var $_elementBlocks = array();
  67. /**
  68. * Block to use for headers
  69. * @var string
  70. */
  71. var $_headerBlock = null;
  72. /**
  73. * Constructor
  74. *
  75. * @param object An HTML_Template_ITX/HTML_Template_Sigma object to use
  76. */
  77. function HTML_QuickForm_Renderer_ITDynamic(&$tpl)
  78. {
  79. $this->HTML_QuickForm_Renderer();
  80. $this->_tpl =& $tpl;
  81. $this->_tpl->setCurrentBlock('qf_main_loop');
  82. }
  83. function finishForm(&$form)
  84. {
  85. // display errors above form
  86. if (!empty($this->_errors) && $this->_tpl->blockExists('qf_error_loop')) {
  87. foreach ($this->_errors as $error) {
  88. $this->_tpl->setVariable('qf_error', $error);
  89. $this->_tpl->parse('qf_error_loop');
  90. }
  91. }
  92. // show required note
  93. if ($this->_showRequired) {
  94. $this->_tpl->setVariable('qf_required_note', $form->getRequiredNote());
  95. }
  96. // assign form attributes
  97. $this->_tpl->setVariable('qf_attributes', $form->getAttributes(true));
  98. // assign javascript validation rules
  99. $this->_tpl->setVariable('qf_javascript', $form->getValidationScript());
  100. }
  101. function renderHeader(&$header)
  102. {
  103. $blockName = $this->_matchBlock($header);
  104. if ('qf_header' == $blockName && isset($this->_headerBlock)) {
  105. $blockName = $this->_headerBlock;
  106. }
  107. $this->_tpl->setVariable('qf_header', $header->toHtml());
  108. $this->_tpl->parse($blockName);
  109. $this->_tpl->parse('qf_main_loop');
  110. }
  111. function renderElement(&$element, $required, $error)
  112. {
  113. $blockName = $this->_matchBlock($element);
  114. // are we inside a group?
  115. if ('qf_main_loop' != $this->_tpl->currentBlock) {
  116. if (0 != $this->_groupElementIdx && $this->_tpl->placeholderExists('qf_separator', $blockName)) {
  117. if (is_array($this->_groupSeparator)) {
  118. $this->_tpl->setVariable('qf_separator', $this->_groupSeparator[($this->_groupElementIdx - 1) % count($this->_groupSeparator)]);
  119. } else {
  120. $this->_tpl->setVariable('qf_separator', (string)$this->_groupSeparator);
  121. }
  122. }
  123. $this->_groupElementIdx++;
  124. } elseif(!empty($error)) {
  125. // show the error message or keep it for later use
  126. if ($this->_tpl->blockExists($blockName . '_error')) {
  127. $this->_tpl->setVariable('qf_error', $error);
  128. } else {
  129. $this->_errors[] = $error;
  130. }
  131. }
  132. // show an '*' near the required element
  133. if ($required) {
  134. $this->_showRequired = true;
  135. if ($this->_tpl->blockExists($blockName . '_required')) {
  136. $this->_tpl->touchBlock($blockName . '_required');
  137. }
  138. }
  139. // Prepare multiple labels
  140. $labels = $element->getLabel();
  141. if (is_array($labels)) {
  142. $mainLabel = array_shift($labels);
  143. } else {
  144. $mainLabel = $labels;
  145. }
  146. // render the element itself with its main label
  147. $this->_tpl->setVariable('qf_element', $element->toHtml());
  148. if ($this->_tpl->placeholderExists('qf_label', $blockName)) {
  149. $this->_tpl->setVariable('qf_label', $mainLabel);
  150. }
  151. // render extra labels, if any
  152. if (is_array($labels)) {
  153. foreach($labels as $key => $label) {
  154. $key = is_int($key)? $key + 2: $key;
  155. if ($this->_tpl->blockExists($blockName . '_label_' . $key)) {
  156. $this->_tpl->setVariable('qf_label_' . $key, $label);
  157. }
  158. }
  159. }
  160. $this->_tpl->parse($blockName);
  161. $this->_tpl->parseCurrentBlock();
  162. }
  163. function renderHidden(&$element)
  164. {
  165. $this->_tpl->setVariable('qf_hidden', $element->toHtml());
  166. $this->_tpl->parse('qf_hidden_loop');
  167. }
  168. function startGroup(&$group, $required, $error)
  169. {
  170. $blockName = $this->_matchBlock($group);
  171. $this->_tpl->setCurrentBlock($blockName . '_loop');
  172. $this->_groupElementIdx = 0;
  173. $this->_groupSeparator = is_null($group->_separator)? '&nbsp;': $group->_separator;
  174. // show an '*' near the required element
  175. if ($required) {
  176. $this->_showRequired = true;
  177. if ($this->_tpl->blockExists($blockName . '_required')) {
  178. $this->_tpl->touchBlock($blockName . '_required');
  179. }
  180. }
  181. // show the error message or keep it for later use
  182. if (!empty($error)) {
  183. if ($this->_tpl->blockExists($blockName . '_error')) {
  184. $this->_tpl->setVariable('qf_error', $error);
  185. } else {
  186. $this->_errors[] = $error;
  187. }
  188. }
  189. $this->_tpl->setVariable('qf_group_label', $group->getLabel());
  190. }
  191. function finishGroup(&$group)
  192. {
  193. $this->_tpl->parse($this->_matchBlock($group));
  194. $this->_tpl->setCurrentBlock('qf_main_loop');
  195. $this->_tpl->parseCurrentBlock();
  196. }
  197. /**
  198. * Returns the name of a block to use for element rendering
  199. *
  200. * If a name was not explicitly set via setElementBlock(), it tries
  201. * the names '{prefix}_{element type}' and '{prefix}_{element}', where
  202. * prefix is either 'qf' or the name of the current group's block
  203. *
  204. * @param object An HTML_QuickForm_element object
  205. * @access private
  206. * @return string block name
  207. */
  208. function _matchBlock(&$element)
  209. {
  210. $name = $element->getName();
  211. $type = $element->getType();
  212. if (isset($this->_elementBlocks[$name]) && $this->_tpl->blockExists($this->_elementBlocks[$name])) {
  213. if (('group' == $type) || ($this->_elementBlocks[$name] . '_loop' != $this->_tpl->currentBlock)) {
  214. return $this->_elementBlocks[$name];
  215. }
  216. }
  217. if ('group' != $type && 'qf_main_loop' != $this->_tpl->currentBlock) {
  218. $prefix = substr($this->_tpl->currentBlock, 0, -5); // omit '_loop' postfix
  219. } else {
  220. $prefix = 'qf';
  221. }
  222. if ($this->_tpl->blockExists($prefix . '_' . $type)) {
  223. return $prefix . '_' . $type;
  224. } elseif ($this->_tpl->blockExists($prefix . '_' . $name)) {
  225. return $prefix . '_' . $name;
  226. } else {
  227. return $prefix . '_element';
  228. }
  229. }
  230. /**
  231. * Sets the block to use for element rendering
  232. *
  233. * @param mixed element name or array ('element name' => 'block name')
  234. * @param string block name if $elementName is not an array
  235. * @access public
  236. * @return void
  237. */
  238. function setElementBlock($elementName, $blockName = null)
  239. {
  240. if (is_array($elementName)) {
  241. $this->_elementBlocks = array_merge($this->_elementBlocks, $elementName);
  242. } else {
  243. $this->_elementBlocks[$elementName] = $blockName;
  244. }
  245. }
  246. /**
  247. * Sets the name of a block to use for header rendering
  248. *
  249. * @param string block name
  250. * @access public
  251. * @return void
  252. */
  253. function setHeaderBlock($blockName)
  254. {
  255. $this->_headerBlock = $blockName;
  256. }
  257. }
  258. ?>