Default.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3. /**
  4. * A concrete renderer for HTML_QuickForm, based on QuickForm 2.x built-in one
  5. *
  6. * PHP versions 4 and 5
  7. *
  8. * LICENSE: This source file is subject to version 3.01 of the PHP license
  9. * that is available through the world-wide-web at the following URI:
  10. * http://www.php.net/license/3_01.txt If you did not receive a copy of
  11. * the PHP License and are unable to obtain it through the web, please
  12. * send a note to license@php.net so we can mail you a copy immediately.
  13. *
  14. * @category HTML
  15. * @package HTML_QuickForm
  16. * @author Alexey Borzov <avb@php.net>
  17. * @author Adam Daniel <adaniel1@eesus.jnj.com>
  18. * @author Bertrand Mansion <bmansion@mamasam.com>
  19. * @copyright 2001-2009 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. * A concrete renderer for HTML_QuickForm, based on QuickForm 2.x built-in one
  26. *
  27. * @category HTML
  28. * @package HTML_QuickForm
  29. * @author Alexey Borzov <avb@php.net>
  30. * @author Adam Daniel <adaniel1@eesus.jnj.com>
  31. * @author Bertrand Mansion <bmansion@mamasam.com>
  32. * @version Release: 3.2.11
  33. * @since 3.0
  34. */
  35. class HTML_QuickForm_Renderer_Default extends HTML_QuickForm_Renderer
  36. {
  37. private $form;
  38. private $customElementTemplate;
  39. /**
  40. * @return mixed
  41. */
  42. public function getCustomElementTemplate()
  43. {
  44. return $this->customElementTemplate;
  45. }
  46. /**
  47. * This template will be taken instead of the default templates by element
  48. * @param string $customElementTemplate
  49. */
  50. public function setCustomElementTemplate($customElementTemplate)
  51. {
  52. $this->customElementTemplate = $customElementTemplate;
  53. }
  54. /**
  55. * The HTML of the form
  56. * @var string
  57. * @access private
  58. */
  59. var $_html;
  60. /**
  61. * Header Template string
  62. * @var string
  63. * @access private
  64. */
  65. var $_headerTemplate =
  66. "\n\t<tr>\n\t\t<td style=\"white-space: nowrap; background-color: #CCCCCC;\" align=\"left\" valign=\"top\" colspan=\"2\"><b>{header}</b></td>\n\t</tr>";
  67. /**
  68. * Element template string
  69. * @var string
  70. * @access private
  71. */
  72. var $_elementTemplate =
  73. "\n\t<tr>\n\t\t<td align=\"right\" valign=\"top\"><!-- BEGIN required --><span style=\"color: #ff0000\">*</span><!-- END required --><b>{label}</b></td>\n\t\t<td valign=\"top\" align=\"left\"><!-- BEGIN error --><span style=\"color: #ff0000\">{error}</span><br /><!-- END error -->\t{element}</td>\n\t</tr>";
  74. /**
  75. * Form template string
  76. * @var string
  77. * @access private
  78. */
  79. var $_formTemplate =
  80. "\n<form{attributes}>\n<div>\n{hidden}<table border=\"0\">\n{content}\n</table>\n</div>\n</form>";
  81. /**
  82. * Required Note template string
  83. * @var string
  84. * @access private
  85. */
  86. var $_requiredNoteTemplate =
  87. "\n\t<tr>\n\t\t<td></td>\n\t<td align=\"left\" valign=\"top\">{requiredNote}</td>\n\t</tr>";
  88. /**
  89. * Array containing the templates for customised elements
  90. * @var array
  91. * @access private
  92. */
  93. var $_templates = array();
  94. /**
  95. * Array containing the templates for group wraps.
  96. *
  97. * These templates are wrapped around group elements and groups' own
  98. * templates wrap around them. This is set by setGroupTemplate().
  99. *
  100. * @var array
  101. * @access private
  102. */
  103. var $_groupWraps = array();
  104. /**
  105. * Array containing the templates for elements within groups
  106. * @var array
  107. * @access private
  108. */
  109. var $_groupTemplates = array();
  110. /**
  111. * True if we are inside a group
  112. * @var bool
  113. * @access private
  114. */
  115. var $_inGroup = false;
  116. /**
  117. * Array with HTML generated for group elements
  118. * @var array
  119. * @access private
  120. */
  121. var $_groupElements = array();
  122. /**
  123. * Template for an element inside a group
  124. * @var string
  125. * @access private
  126. */
  127. var $_groupElementTemplate = '';
  128. /**
  129. * HTML that wraps around the group elements
  130. * @var string
  131. * @access private
  132. */
  133. var $_groupWrap = '';
  134. /**
  135. * HTML for the current group
  136. * @var string
  137. * @access private
  138. */
  139. var $_groupTemplate = '';
  140. /**
  141. * Collected HTML of the hidden fields
  142. * @var string
  143. * @access private
  144. */
  145. var $_hiddenHtml = '';
  146. /**
  147. * Constructor
  148. *
  149. * @access public
  150. */
  151. public function __construct()
  152. {
  153. parent::__construct();
  154. } // end constructor
  155. /**
  156. * returns the HTML generated for the form
  157. *
  158. * @access public
  159. * @return string
  160. */
  161. public function toHtml()
  162. {
  163. // _hiddenHtml is cleared in finishForm(), so this only matters when
  164. // finishForm() was not called (e.g. group::toHtml(), bug #3511)
  165. return $this->_hiddenHtml . $this->_html;
  166. } // end func toHtml
  167. /**
  168. * Called when visiting a form, before processing any form elements
  169. *
  170. * @param HTML_QuickForm form object being visited
  171. * @access public
  172. * @return void
  173. */
  174. function startForm(&$form)
  175. {
  176. $this->setForm($form);
  177. $this->_html = '';
  178. $this->_hiddenHtml = '';
  179. }
  180. /**
  181. * @return FormValidator
  182. */
  183. public function getForm()
  184. {
  185. return $this->form;
  186. }
  187. /**
  188. * @param mixed $form
  189. */
  190. public function setForm($form)
  191. {
  192. $this->form = $form;
  193. } // end func startForm
  194. /**
  195. * Called when visiting a form, after processing all form elements
  196. * Adds required note, form attributes, validation javascript and form content.
  197. *
  198. * @param HTML_QuickForm form object being visited
  199. * @access public
  200. * @return void
  201. */
  202. public function finishForm(&$form)
  203. {
  204. // add a required note, if one is needed
  205. if (!empty($form->_required) && !$form->_freezeAll) {
  206. $this->_html .= str_replace('{requiredNote}', $form->getRequiredNote(), $this->_requiredNoteTemplate);
  207. }
  208. // add form attributes and content
  209. $html = str_replace('{attributes}', $form->getAttributes(true), $this->_formTemplate);
  210. if (strpos($this->_formTemplate, '{hidden}')) {
  211. $html = str_replace('{hidden}', $this->_hiddenHtml, $html);
  212. } else {
  213. $this->_html .= $this->_hiddenHtml;
  214. }
  215. $this->_hiddenHtml = '';
  216. $this->_html = str_replace('{content}', $this->_html, $html);
  217. // add a validation script
  218. if ('' != ($script = $form->getValidationScript())) {
  219. $this->_html = $script . "\n" . $this->_html;
  220. }
  221. } // end func finishForm
  222. /**
  223. * Called when visiting a header element
  224. *
  225. * @param HTML_QuickForm_header header element being visited
  226. * @access public
  227. * @return void
  228. */
  229. function renderHeader(&$header)
  230. {
  231. $name = $header->getName();
  232. if (!empty($name) && isset($this->_templates[$name])) {
  233. $this->_html .= str_replace('{header}', $header->toHtml(), $this->_templates[$name]);
  234. } else {
  235. $this->_html .= str_replace('{header}', $header->toHtml(), $this->_headerTemplate);
  236. }
  237. } // end func renderHeader
  238. /**
  239. * Helper method for renderElement
  240. *
  241. * @param HTML_QuickForm_element $element
  242. * @param bool Whether an element is required
  243. * @param string $required Error message associated with the element
  244. * @param string $error Label for ID
  245. * @access private
  246. * @see renderElement()
  247. * @return string Html for element
  248. */
  249. private function _prepareTemplate(HTML_QuickForm_element $element, $required, $error)
  250. {
  251. $name = $element->getName();
  252. $label = $element->getLabel();
  253. $labelForId = $element->getAttribute('id');
  254. $extraLabelClass = $element->getAttribute('extra_label_class');
  255. $icon = $element->getIconToHtml();
  256. if (is_array($label)) {
  257. $nameLabel = array_shift($label);
  258. // In some cases, label (coming from display_text) might be a
  259. // double-level array. In this case, take the first item of the
  260. // sub-array as label
  261. if (is_array($nameLabel)) {
  262. $nameLabel = $nameLabel[0];
  263. }
  264. } else {
  265. $nameLabel = $label;
  266. }
  267. $labelFor = !empty($labelForId) ? 'for="' . $labelForId . '"' : 'for="' . $element->getName() . '"';
  268. if (isset($this->_templates[$name])) {
  269. // Custom template
  270. $html = str_replace('{label}', $nameLabel, $this->_templates[$name]);
  271. } else {
  272. $customElementTemplate = $this->getCustomElementTemplate();
  273. if (empty($customElementTemplate)) {
  274. if (method_exists($element, 'getTemplate')) {
  275. $template = $element->getTemplate(
  276. $this->getForm()->getLayout()
  277. );
  278. if ($element->isFrozen()) {
  279. $customFrozentemplate = $element->getCustomFrozenTemplate();
  280. if (!empty($customFrozentemplate)) {
  281. $template = $customFrozentemplate;
  282. }
  283. }
  284. } else {
  285. $template = $this->getForm()->getDefaultElementTemplate();
  286. }
  287. } else {
  288. $template = $customElementTemplate;
  289. }
  290. $html = str_replace('{label}', $nameLabel, $template);
  291. }
  292. $html = str_replace('{label-for}', $labelFor, $html);
  293. $html = str_replace('{icon}', $icon, $html);
  294. $html = str_replace('{extra_label_class}', $extraLabelClass, $html);
  295. if ($required) {
  296. $html = str_replace('<!-- BEGIN required -->', '', $html);
  297. $html = str_replace('<!-- END required -->', '', $html);
  298. } else {
  299. $html = preg_replace("/([ \t\n\r]*)?<!-- BEGIN required -->.*<!-- END required -->([ \t\n\r]*)?/isU", '', $html);
  300. }
  301. if (isset($error)) {
  302. $html = str_replace('{error}', $error, $html);
  303. $html = str_replace('{error_class}', 'error has-error', $html);
  304. $html = str_replace('<!-- BEGIN error -->', '', $html);
  305. $html = str_replace('<!-- END error -->', '', $html);
  306. } else {
  307. $html = str_replace('{error_class}', '', $html);
  308. $html = preg_replace("/([ \t\n\r]*)?<!-- BEGIN error -->.*<!-- END error -->([ \t\n\r]*)?/isU", '', $html);
  309. }
  310. if (is_array($label)) {
  311. foreach ($label as $key => $text) {
  312. $key = is_int($key)? $key + 2: $key;
  313. $html = str_replace("{label_{$key}}", $text, $html);
  314. $html = str_replace("<!-- BEGIN label_{$key} -->", '', $html);
  315. $html = str_replace("<!-- END label_{$key} -->", '', $html);
  316. }
  317. }
  318. if (strpos($html, '{label_')) {
  319. $html = preg_replace('/\s*<!-- BEGIN label_(\S+) -->.*<!-- END label_\1 -->\s*/is', '', $html);
  320. }
  321. return $html;
  322. }
  323. /**
  324. * Renders an element Html
  325. * Called when visiting an element
  326. *
  327. * @param HTML_QuickForm_element form element being visited
  328. * @param bool Whether an element is required
  329. * @param string An error message associated with an element
  330. * @access public
  331. * @return void
  332. */
  333. public function renderElement(&$element, $required, $error)
  334. {
  335. if (!$this->_inGroup) {
  336. $html = $this->_prepareTemplate(
  337. $element,
  338. $required,
  339. $error
  340. );
  341. $this->_html .= str_replace('{element}', $element->toHtml(), $html);
  342. } elseif (!empty($this->_groupElementTemplate)) {
  343. $html = str_replace('{label}', $element->getLabel(), $this->_groupElementTemplate);
  344. $html = str_replace('{label-for}', $element->getLabelFor(), $this->_groupElementTemplate);
  345. if ($required) {
  346. $html = str_replace('<!-- BEGIN required -->', '', $html);
  347. $html = str_replace('<!-- END required -->', '', $html);
  348. } else {
  349. $html = preg_replace("/([ \t\n\r]*)?<!-- BEGIN required -->.*<!-- END required -->([ \t\n\r]*)?/isU", '', $html);
  350. }
  351. $this->_groupElements[] = str_replace('{element}', $element->toHtml(), $html);
  352. } else {
  353. $this->_groupElements[] = $element->toHtml();
  354. }
  355. } // end func renderElement
  356. /**
  357. * Renders an hidden element
  358. * Called when visiting a hidden element
  359. *
  360. * @param HTML_QuickForm_element form element being visited
  361. * @access public
  362. * @return void
  363. */
  364. function renderHidden(&$element)
  365. {
  366. $this->_hiddenHtml .= $element->toHtml() . "\n";
  367. } // end func renderHidden
  368. /**
  369. * Called when visiting a raw HTML/text pseudo-element
  370. *
  371. * @param HTML_QuickForm_html element being visited
  372. * @access public
  373. * @return void
  374. */
  375. function renderHtml(&$data)
  376. {
  377. $this->_html .= $data->toHtml();
  378. } // end func renderHtml
  379. /**
  380. * Called when visiting a group, before processing any group elements
  381. *
  382. * @param HTML_QuickForm_group group being visited
  383. * @param bool Whether a group is required
  384. * @param string An error message associated with a group
  385. * @access public
  386. * @return void
  387. */
  388. function startGroup(&$group, $required, $error)
  389. {
  390. $name = $group->getName();
  391. $this->_groupTemplate = $this->_prepareTemplate($group, $required, $error);
  392. $this->_groupElementTemplate = empty($this->_groupTemplates[$name])? '': $this->_groupTemplates[$name];
  393. $this->_groupWrap = empty($this->_groupWraps[$name])? '': $this->_groupWraps[$name];
  394. $this->_groupElements = array();
  395. $this->_inGroup = true;
  396. } // end func startGroup
  397. /**
  398. * Called when visiting a group, after processing all group elements
  399. *
  400. * @param HTML_QuickForm_group group being visited
  401. * @access public
  402. * @return void
  403. */
  404. function finishGroup(&$group)
  405. {
  406. $separator = $group->_separator;
  407. if (is_array($separator)) {
  408. $count = count($separator);
  409. $html = '';
  410. for ($i = 0; $i < count($this->_groupElements); $i++) {
  411. $html .= (0 == $i? '': $separator[($i - 1) % $count]) . $this->_groupElements[$i];
  412. }
  413. } else {
  414. if (is_null($separator)) {
  415. $separator = '&nbsp;';
  416. }
  417. $html = implode((string)$separator, $this->_groupElements);
  418. }
  419. if (!empty($this->_groupWrap)) {
  420. $html = str_replace('{content}', $html, $this->_groupWrap);
  421. }
  422. $this->_html .= str_replace('{element}', $html, $this->_groupTemplate);
  423. $this->_inGroup = false;
  424. } // end func finishGroup
  425. /**
  426. * Sets element template
  427. *
  428. * @param string The HTML surrounding an element
  429. * @param string (optional) Name of the element to apply template for
  430. * @access public
  431. * @return void
  432. */
  433. function setElementTemplate($html, $element = null)
  434. {
  435. if (is_null($element)) {
  436. $this->_elementTemplate = $html;
  437. } else {
  438. $this->_templates[$element] = $html;
  439. }
  440. } // end func setElementTemplate
  441. /**
  442. * Sets template for a group wrapper
  443. *
  444. * This template is contained within a group-as-element template
  445. * set via setTemplate() and contains group's element templates, set
  446. * via setGroupElementTemplate()
  447. *
  448. * @param string The HTML surrounding group elements
  449. * @param string Name of the group to apply template for
  450. * @access public
  451. * @return void
  452. */
  453. function setGroupTemplate($html, $group)
  454. {
  455. $this->_groupWraps[$group] = $html;
  456. } // end func setGroupTemplate
  457. /**
  458. * Sets element template for elements within a group
  459. *
  460. * @param string The HTML surrounding an element
  461. * @param string Name of the group to apply template for
  462. * @access public
  463. * @return void
  464. */
  465. function setGroupElementTemplate($html, $group)
  466. {
  467. $this->_groupTemplates[$group] = $html;
  468. } // end func setGroupElementTemplate
  469. /**
  470. * Sets header template
  471. *
  472. * @param string The HTML surrounding the header
  473. * @access public
  474. * @return void
  475. */
  476. function setHeaderTemplate($html)
  477. {
  478. $this->_headerTemplate = $html;
  479. } // end func setHeaderTemplate
  480. /**
  481. * Sets form template
  482. *
  483. * @param string The HTML surrounding the form tags
  484. * @access public
  485. * @return void
  486. */
  487. function setFormTemplate($html) {
  488. $this->_formTemplate = $html;
  489. } // end func setFormTemplate
  490. /**
  491. * Sets the note indicating required fields template
  492. *
  493. * @param string The HTML surrounding the required note
  494. * @access public
  495. * @return void
  496. */
  497. function setRequiredNoteTemplate($html)
  498. {
  499. $this->_requiredNoteTemplate = $html;
  500. } // end func setRequiredNoteTemplate
  501. /**
  502. * Clears all the HTML out of the templates that surround notes, elements, etc.
  503. * Useful when you want to use addData() to create a completely custom form look
  504. *
  505. * @access public
  506. * @return void
  507. */
  508. function clearAllTemplates()
  509. {
  510. $this->setElementTemplate('{element}');
  511. $this->setFormTemplate("\n\t<form{attributes}>{content}\n\t</form>\n");
  512. $this->setRequiredNoteTemplate('');
  513. $this->_templates = array();
  514. } // end func clearAllTemplates
  515. } // end class HTML_QuickForm_Renderer_Default