PageRenderTime 60ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/framework/Model/lib/Horde/Core/Form/Renderer/Html.php

https://github.com/wrobel/horde
PHP | 453 lines | 324 code | 60 blank | 69 comment | 52 complexity | 2176463fc4d62bbb317f8a39baac40a7 MD5 | raw file
Possible License(s): BSD-2-Clause, AGPL-1.0, LGPL-2.1, LGPL-3.0, BSD-3-Clause, LGPL-2.0, GPL-2.0
  1. <?php
  2. /**
  3. */
  4. class Horde_Core_Form_Renderer_Html extends Horde_Core_Form_Renderer
  5. {
  6. protected $_enctype = 'multipart/form-data';
  7. protected function _renderSectionTabs($form)
  8. {
  9. /* If javascript is not available, do not render tabs. */
  10. if (!$GLOBALS['browser']->hasFeature('javascript')) {
  11. return;
  12. }
  13. $open_section = $form->getOpenSection();
  14. /* Add the javascript for the toggling the sections. */
  15. Horde::addScriptFile('form_sections.js', 'horde');
  16. echo '<script type="text/javascript">' . "\n" .
  17. sprintf('var sections_%1$s = new Horde_Form_Sections(\'%1$s\', \'%2$s\');',
  18. $form->getName(),
  19. $open_section) .
  20. '</script>';
  21. /* Loop through the sections and print out a tab for each. */
  22. echo "<div class=\"tabset\">\n";
  23. $js = array();
  24. foreach ($form->_sections as $section => $val) {
  25. $class = ($section == $open_section) ? ' class="activeTab"' : '';
  26. $tabid = htmlspecialchars($form->getName() . '_tab_' . $section);
  27. $js[$linkid] = sprintf('sections_%s.toggle(\'%s\'); return false;"',
  28. $form->getName(),
  29. $section);
  30. printf('<div%s id="%s"><a href="#" id="%s">%s%s</a></div>' . "\n",
  31. $class,
  32. $tabid,
  33. '_tablink_' . $section,
  34. $form->getSectionImage($section),
  35. $form->getSectionDesc($section));
  36. }
  37. echo "</div>\n";
  38. // This doesn't help a whole lot now, but if there is a way to
  39. // buffer output of JS, then we can keep JS separated from
  40. // markup, whereas before the onclicks were assigned as an
  41. // HTML attribute.
  42. echo '<script type="text/javascript">' . "\n";
  43. echo 'if (document.getElementById) {' . "\n";
  44. echo ' addEvent(window, \'load\', function() {' . "\n";
  45. foreach ($js as $id => $onclick) {
  46. $line = '
  47. if (document.getElementById(%1$s)){
  48. document.getElementById(%1$s).onclick = function() {
  49. %2$s
  50. };
  51. }';
  52. printf($line, $id, $onclick);
  53. }
  54. echo ' });}</script>' . "\n";
  55. }
  56. protected function _renderSectionBegin($form, $section)
  57. {
  58. // Stripe alternate rows if that option is turned on.
  59. if ($this->_stripedRows) {
  60. Horde::addScriptFile('stripe.js', 'horde');
  61. $class = 'striped';
  62. } else {
  63. $class = '';
  64. }
  65. $open_section = $form->getOpenSection();
  66. if (empty($open_section)) {
  67. $open_section = '__base';
  68. }
  69. // include a general class name for styling purposes. also helps select
  70. // ULs, which only get a className currently if they are striped.
  71. printf('<fieldset id="%s" class="%s form-section %s">',
  72. htmlspecialchars($form->getName() . '_section_' . $section),
  73. ($open_section == $section ? 'form-sectionshown' : 'form-sectionhidden'),
  74. $class);
  75. }
  76. protected function _renderSectionEnd()
  77. {
  78. echo '</fieldset>';
  79. }
  80. public function preserveVarByPost($vars, $varname, $alt_varname = '')
  81. {
  82. $value = $vars->getExists($varname, $wasset);
  83. if ($alt_varname) {
  84. $varname = $alt_varname;
  85. }
  86. if ($wasset) {
  87. $this->_preserveVarByPost($varname, $value);
  88. }
  89. }
  90. function _preserveVarByPost($varname, $value)
  91. {
  92. if (is_array($value)) {
  93. foreach ($value as $id => $val) {
  94. $this->_preserveVarByPost($varname . '[' . $id . ']', $val);
  95. }
  96. } else {
  97. $varname = htmlspecialchars($varname);
  98. $value = htmlspecialchars($value);
  99. printf('<input type="hidden" id="%1$s" name="%1$s" value="%2$s" />'."\n",
  100. $varname,
  101. $value);
  102. }
  103. }
  104. function listFormVars($form)
  105. {
  106. $variables = $form->getVariables(true, true);
  107. $vars = array();
  108. if ($variables) {
  109. foreach ($variables as $var) {
  110. if (is_object($var)) {
  111. if (!$var->isReadonly()) {
  112. $vars[$var->getVarName()] = 1;
  113. }
  114. } else {
  115. $vars[$var] = 1;
  116. }
  117. }
  118. }
  119. echo '<input type="hidden" name="_formvars" value="'
  120. . htmlspecialchars(serialize($vars))
  121. . '" />';
  122. }
  123. public function renderActive($form, $action, $method = 'get', $enctype = null, $focus = true)
  124. {
  125. $this->_name = $form->getName();
  126. echo "<form class=\"horde-form\" action=\"$action\" method=\"$method\""
  127. . (empty($this->_name) ? '' : ' id="' . $this->_name. '"')
  128. . (is_null($this->_enctype) ? '' : ' enctype="' . $this->_enctype . '"')
  129. . ">\n";
  130. echo Horde_Util::formInput();
  131. $this->listFormVars($form);
  132. if (!empty($this->_name)) {
  133. $this->_preserveVarByPost('formname', $this->_name);
  134. }
  135. if ($form->useToken()) {
  136. $this->_preserveVarByPost($this->_name . '_formToken', Horde_Token::generateId($this->_name));
  137. }
  138. if (count($form->getSections())) {
  139. $this->_preserveVarByPost('__formOpenSection', $form->getOpenSection());
  140. }
  141. $vars = $form->getVars();
  142. $variables = $form->getVariables();
  143. foreach ($variables as $var) {
  144. if ($var->getOption('trackchange')) {
  145. $varname = $var->getVarName();
  146. $this->preserveVarByPost($vars, $varname, '__old_' . $varname);
  147. }
  148. }
  149. foreach ($form->getHiddenVariables() as $var) {
  150. $this->preserveVarByPost($vars, $var->getVarName());
  151. }
  152. $this->_renderBeginActive($form->getTitle());
  153. $this->_renderForm($form, true);
  154. $this->submit($this->_submit, $this->_reset);
  155. echo "\n</fieldset>\n</form>\n";
  156. if ($focus && !empty($this->_firstField)) {
  157. echo '<script type="text/javascript">
  158. try {
  159. document.getElementById("'. $this->_firstField .'").focus();
  160. } catch (e) {}
  161. </script>
  162. ';
  163. }
  164. }
  165. function renderInactive($form)
  166. {
  167. $this->_name = $form->getName();
  168. $this->_renderBeginInactive($form->getTitle());
  169. $this->_renderForm($form, false);
  170. }
  171. function _renderForm($form, $active)
  172. {
  173. $vars = $form->getVars();
  174. /* If help is present 3 columns are needed. */
  175. $this->_cols = $form->hasHelp() ? 3 : 2;
  176. $variables = $form->getVariables(false);
  177. /* Check for a form token error. */
  178. if (($tokenError = $form->getError('_formToken')) !== null) {
  179. printf('<p class="form-error">%s</p>'."\n", $tokenError);
  180. }
  181. $error_section = null;
  182. reset($variables);
  183. if (count($variables) > 1 || key($variables) != '__base') {
  184. $this->_renderSectionTabs($form);
  185. }
  186. foreach ($variables as $section_id => $section) {
  187. $this->_renderSectionBegin($form, $section_id);
  188. foreach ($section as $var) {
  189. switch (get_class($var->type)) {
  190. case 'Horde_Form_Type_Header':
  191. $this->_renderHeader($var->getHumanName(), $form->getError($var->getVarName()));
  192. break;
  193. case 'Horde_Form_Type_Description':
  194. $this->_renderDescription($var->getHumanName());
  195. break;
  196. case 'Horde_Form_Type_Spacer':
  197. $this->_renderSpacer();
  198. break;
  199. default:
  200. $isInput = ($active && !$var->isReadonly());
  201. $format = $isInput ? 'Input' : 'Display';
  202. $begin = "_renderVar${format}Begin";
  203. $end = "_renderVar${format}End";
  204. $this->$begin($form, $var);
  205. echo $this->_varRender($form, $var, $vars, $isInput);
  206. $this->$end($form, $var);
  207. /* Print any javascript if actions present. */
  208. if ($var->hasAction()) {
  209. $var->_action->printJavaScript();
  210. }
  211. /* Keep first field. */
  212. if ($active && empty($this->_firstField) && !$var->isReadonly()
  213. && !$var->isHidden()) {
  214. $this->_firstField = $var->getVarName();
  215. }
  216. /* Keep section with first error. */
  217. if (is_null($error_section) && $form->getError($var)) {
  218. $error_section = $section_id;
  219. }
  220. }
  221. }
  222. $this->_renderSectionEnd();
  223. }
  224. if (!is_null($error_section)) {
  225. echo '<script type="text/javascript">' .
  226. "\n" . sprintf('sections_%s.toggle(\'%s\');',
  227. $form->getName(),
  228. $error_section) .
  229. "\n</script>\n";
  230. }
  231. echo '</fieldset>' . $this->_varRenderEnd();
  232. }
  233. function submit($submit = null, $reset = false)
  234. {
  235. if (is_null($submit) || empty($submit)) {
  236. $submit = Horde_Model_Translation::t("Submit");
  237. }
  238. if ($reset === true) {
  239. $reset = Horde_Model_Translation::t("Reset");
  240. }
  241. $this->_renderSubmit($submit, $reset);
  242. }
  243. /**
  244. * Implementation specific begin function.
  245. */
  246. function _renderBeginActive($name)
  247. {
  248. echo '<fieldset class="horde-form" id="fieldset_' . htmlspecialchars($this->_name) . '">'."\n";
  249. if ($this->_showHeader) {
  250. $this->_renderSectionHeader($name);
  251. }
  252. if ($this->_requiredLegend) {
  253. echo '<div class="form-error-example">' . $this->_requiredMarker
  254. . ' &#61; ' . Horde_Model_Translation::t("Required Field") . '</div>'."\n";
  255. }
  256. }
  257. /**
  258. * Implementation specific begin function.
  259. */
  260. function _renderBeginInactive($name)
  261. {
  262. echo '<fieldset class="horde-form" id="fieldset_' . htmlspecialchars($this->_name) . '">';
  263. if ($this->_showHeader) {
  264. $this->_renderSectionHeader($name);
  265. }
  266. }
  267. function _renderHeader($header, $error = '')
  268. {
  269. echo '<div class="form-header">'. $header . '</div>';
  270. if (!empty($error)) {
  271. echo '<div class="form-error">'. $error . '</div>';
  272. }
  273. }
  274. function _renderDescription($description)
  275. {
  276. echo '<div class="form-description">'. $description . '</div>';
  277. }
  278. function _renderSpacer()
  279. {
  280. // TODO: fix this later so we're not inserting nonsemantic elements just for spacing
  281. // ... maybe append form-spacer to class of next or previous element
  282. echo '<div class="form-spacer">&nbsp;</div>';
  283. }
  284. function _renderSubmit($submit, $reset)
  285. {
  286. echo '<fieldset class="form-buttons">'."\n";
  287. if (!is_array($submit)) $submit = array($submit);
  288. foreach ($submit as $submitbutton) {
  289. echo '<input class="button" name="submitbutton" type="submit"';
  290. // allow for default-value submit buttons (e.g. _renderSubmit(""))
  291. if (!empty($submitbutton)) {
  292. echo ' value="'. $submitbutton .'"';
  293. }
  294. echo ' />'."\n";
  295. }
  296. if (!empty($reset)) {
  297. echo '<input class="button" name="resetbutton" type="reset"
  298. value="'. $reset .'" />'."\n";
  299. }
  300. }
  301. /**
  302. * Renders the beginning of an writeable form entry, including the label
  303. * and any form error related to this variable.
  304. *
  305. * @access private
  306. * @author Matt Warden <mwarden@gmail.com>
  307. * @author Robert E. Coyle <robertecoyle@hotmail.com>
  308. */
  309. function _renderVarInputBegin($form, $var, $readonly = false)
  310. {
  311. // get error message for variable, if any
  312. $message = $form->getError($var);
  313. // if no message, then no error
  314. $isvalid = empty($message);
  315. $classnames = 'form-input'
  316. . (!$isvalid ? ' form-error' : '')
  317. . ($var->isRequired() ? ' form-required' : '');
  318. echo '<div class="', $classnames, '">';
  319. if (!$isvalid) {
  320. echo '<p class="form-error">', $message, '</p>', "\n";
  321. }
  322. printf('<label%s>%s</label>',
  323. ($readonly ? '' : ' for="'. $var->getVarName() .'"'),
  324. $var->getHumanName());
  325. }
  326. /**
  327. * Renders the end of an writeable form entry, including any form notes
  328. * and help info.
  329. *
  330. * @access private
  331. * @author Matt Warden <mwarden@gmail.com>
  332. * @author Robert E. Coyle <robertecoyle@hotmail.com>
  333. */
  334. function _renderVarInputEnd($form, $var)
  335. {
  336. /* Display any help for the field. */
  337. if ($var->hasHelp()) {
  338. global $registry;
  339. if (isset($registry) && is_a($registry, 'Registry')) {
  340. $help = Horde_Help::link($GLOBALS['registry']->getApp(), $var->getHelp());
  341. } else {
  342. $help = @htmlspecialchars($var->getHelp());
  343. }
  344. echo '<p class="form-hint">', $help, '</p>';
  345. }
  346. /* Display any description for the field. */
  347. if ($var->hasDescription()) {
  348. echo '<div class="form-note"><p>', $var->getDescription(), '</p></div>';
  349. } else {
  350. echo '<br class="clear" />';
  351. }
  352. echo '</div>';
  353. }
  354. /**
  355. * Renders the beginning of a readonly form entry.
  356. *
  357. * @access private
  358. * @author Matt Warden <mwarden@gmail.com>
  359. * @author Robert E. Coyle <robertecoyle@hotmail.com>
  360. */
  361. function _renderVarDisplayBegin($form, $var)
  362. {
  363. return $this->_renderVarInputBegin($form, $var, true);
  364. }
  365. /**
  366. * Renders the end of a readonly form entry. Help and notes are not
  367. * applicable.
  368. *
  369. * @access private
  370. * @author Matt Warden <mwarden@gmail.com>
  371. * @author Robert E. Coyle <robertecoyle@hotmail.com>
  372. */
  373. function _renderVarDisplayEnd()
  374. {
  375. echo '</div>';
  376. }
  377. /**
  378. * Renders the header for the section.
  379. *
  380. * @access private
  381. * @author Matt Warden <mwarden@gmail.com>
  382. * @author Robert E. Coyle <robertecoyle@hotmail.com>
  383. * @param string $title section header title
  384. */
  385. function _renderSectionHeader($title)
  386. {
  387. if (!empty($title)) {
  388. echo "\n".'<legend>';
  389. echo $this->_encodeTitle ? htmlspecialchars($title) : $title;
  390. echo '</legend>'."\n";
  391. }
  392. }
  393. }