PageRenderTime 36ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/sally/core/lib/sly/Form.php

https://bitbucket.org/SallyCMS/0.7
PHP | 432 lines | 157 code | 43 blank | 232 comment | 10 complexity | 0d3795f0eb420cceb78e9b1420235ea2 MD5 | raw file
  1. <?php
  2. /*
  3. * Copyright (c) 2013, webvariants GbR, http://www.webvariants.de
  4. *
  5. * This file is released under the terms of the MIT license. You can find the
  6. * complete text in the attached LICENSE file or online at:
  7. *
  8. * http://www.opensource.org/licenses/mit-license.php
  9. */
  10. /**
  11. * A backend form
  12. *
  13. * This class renders the normal backend form, used on many Sally pages. The
  14. * form consists of multiple fieldsets (beginning with a implicitly created one)
  15. * and can also contain hidden values. It also supports direct access to all
  16. * relevant four buttons (submit, reset, delete, apply).
  17. *
  18. * If you want to build you own form, this is the class you want to use.
  19. *
  20. * @see http://docs.webvariants.de/sallycms/latest/sallycms/forms/index.html
  21. * @ingroup form
  22. * @author Christoph
  23. */
  24. class sly_Form extends sly_Form_Base {
  25. protected $action; ///< string
  26. protected $method; ///< string
  27. protected $title; ///< string
  28. protected $name; ///< string
  29. protected $id; ///< string
  30. protected $classes; ///< array
  31. protected $enctype; ///< string
  32. protected $submitButton; ///< sly_Form_Input_Button
  33. protected $resetButton; ///< sly_Form_Input_Button
  34. protected $deleteButton; ///< sly_Form_Input_Button
  35. protected $applyButton; ///< sly_Form_Input_Button
  36. protected $fieldsets; ///< array
  37. protected $currentFieldset; ///< sly_Form_Fieldset
  38. protected $focussedElement; ///< string
  39. protected $buttonClasses; ///< array
  40. /**
  41. * Constructor
  42. *
  43. * Creates a new form and the first fieldset. It also sets up the submit and
  44. * reset button.
  45. *
  46. * @param string $action the action (in most cases, a URL like 'index.php')
  47. * @param string $method the HTTP method (GET or POST)
  48. * @param string $title the form title (is the title of the first fieldset)
  49. * @param string $name the form name (optional)
  50. * @param string $id the form ID (optional)
  51. */
  52. public function __construct($action, $method, $title, $name = '', $id = '') {
  53. $this->action = $action;
  54. $this->method = strtoupper($method) === 'GET' ? 'GET' : 'POST';
  55. $this->title = $title;
  56. $this->name = $name;
  57. $this->id = $id;
  58. $this->enctype = false;
  59. $this->classes = array();
  60. $this->submitButton = new sly_Form_Input_Button('submit', 'submit', t('save'));
  61. $this->resetButton = new sly_Form_Input_Button('reset', 'reset', t('reset'));
  62. $this->deleteButton = null;
  63. $this->applyButton = null;
  64. $this->hiddenValues = array();
  65. $this->fieldsets = array();
  66. $this->currentFieldset = null;
  67. $this->focussedElement = '';
  68. $this->buttonClasses = array('submit' => array('sly-form-submit'), 'reset' => array(), 'delete' => array('sly-form-submit'), 'apply' => array('sly-form-submit'));
  69. }
  70. /**
  71. * Set the encoding
  72. *
  73. * Use this method to alter the encoding, for example when you use the form
  74. * to upload files.
  75. *
  76. * @param string $enctype the new enctype
  77. * @return sly_Form the current object
  78. */
  79. public function setEncType($enctype) {
  80. $this->enctype = trim($enctype);
  81. return $this;
  82. }
  83. /**
  84. * Start a new fieldset
  85. *
  86. * This method creates a new fieldset, appends it to the form and marks it
  87. * as active (that means that new elements will be appended to this one).
  88. * The fieldset can use more than one column, independently from the other
  89. * fieldsets in this form. Note that fieldsets with more than one column
  90. * cannot contain multilingual form elements (because the XHTML would be
  91. * so darn complex, that we just disabled this option).
  92. *
  93. * @param string $title the fieldset title
  94. * @param string $id the HTML id
  95. * @param int $columns the number of columns
  96. * @return sly_Form_Fieldset the newly created fieldset
  97. */
  98. public function beginFieldset($title, $id = null, $columns = 1) {
  99. $this->currentFieldset = new sly_Form_Fieldset($title, $id, $columns);
  100. $this->fieldsets[] = $this->currentFieldset;
  101. return $this->currentFieldset;
  102. }
  103. /**
  104. * Adds a new row of elements
  105. *
  106. * This method will add a new row to the currently active fieldset. In most
  107. * cases, this is the last one, that has been created.
  108. *
  109. * @param array $row the array of form elements
  110. * @return sly_Form the current object
  111. */
  112. public function addRow(array $row) {
  113. if ($this->currentFieldset === null) {
  114. $this->beginFieldset($this->title);
  115. }
  116. $this->currentFieldset->addRow($row);
  117. return $this;
  118. }
  119. /**
  120. * Adds a new fieldset
  121. *
  122. * This methods just adds a new fieldset to the form and marks it as active.
  123. *
  124. * @param sly_Form_Fieldset $fieldset the fieldset to add
  125. * @return sly_Form the current object
  126. */
  127. public function addFieldset(sly_Form_Fieldset $fieldset) {
  128. $this->fieldsets[] = $fieldset;
  129. $this->currentFieldset = null;
  130. return $this;
  131. }
  132. /**
  133. * Set the submit button
  134. *
  135. * This method allows access to the special submit button. Use it to
  136. * overwrite the default button with your own (giving a new button) or to
  137. * remove the button (giving null).
  138. *
  139. * @param sly_Form_Input_Button $submitButton the new submit button
  140. * @return sly_Form the current object
  141. */
  142. public function setSubmitButton(sly_Form_Input_Button $submitButton = null) {
  143. $this->submitButton = $submitButton;
  144. return $this;
  145. }
  146. /**
  147. * Set the reset button
  148. *
  149. * This method allows access to the special reset button. Use it to
  150. * overwrite the default button with your own (giving a new button) or to
  151. * remove the button (giving null).
  152. *
  153. * @param sly_Form_Input_Button $resetButton the new reset button
  154. * @return sly_Form the current object
  155. */
  156. public function setResetButton(sly_Form_Input_Button $resetButton = null) {
  157. $this->resetButton = $resetButton;
  158. return $this;
  159. }
  160. /**
  161. * Set the apply button
  162. *
  163. * This method allows access to the special apply button. Use it to
  164. * overwrite the default button with your own (giving a new button) or to
  165. * remove the button (giving null).
  166. * This button does not exist by default.
  167. *
  168. * @param sly_Form_Input_Button $applyButton the new apply button
  169. * @return sly_Form the current object
  170. */
  171. public function setApplyButton(sly_Form_Input_Button $applyButton = null) {
  172. $this->applyButton = $applyButton;
  173. return $this;
  174. }
  175. /**
  176. * Set the delete button
  177. *
  178. * This method allows access to the special delete button. Use it to
  179. * overwrite the default button with your own (giving a new button) or to
  180. * remove the button (giving null).
  181. * This button does not exist by default.
  182. *
  183. * @param sly_Form_Input_Button $deleteButton the new delete button
  184. * @return sly_Form the current object
  185. */
  186. public function setDeleteButton(sly_Form_Input_Button $deleteButton = null) {
  187. $this->deleteButton = $deleteButton;
  188. return $this;
  189. }
  190. /**
  191. * Returns the submit button
  192. *
  193. * @return sly_Form_Input_Button the submit button
  194. */
  195. public function getSubmitButton() {
  196. return $this->submitButton;
  197. }
  198. /**
  199. * Returns the reset button
  200. *
  201. * @return sly_Form_Input_Button the reset button
  202. */
  203. public function getResetButton() {
  204. return $this->resetButton;
  205. }
  206. /**
  207. * Returns the apply button
  208. *
  209. * @return sly_Form_Input_Button the apply button
  210. */
  211. public function getApplyButton() {
  212. return $this->applyButton;
  213. }
  214. /**
  215. * Returns the delete button
  216. *
  217. * @return sly_Form_Input_Button the delete button
  218. */
  219. public function getDeleteButton() {
  220. return $this->deleteButton;
  221. }
  222. /**
  223. * Adds a new CSS class to a button
  224. *
  225. * This methods adds a class to a specific button. $type can be 'submit',
  226. * 'reset', 'delete' or 'apply'. The list of classes per type will be unique.
  227. *
  228. * @param string $type the button type (submit, reset, delete or apply)
  229. * @param string $class the new CSS class
  230. * @return sly_Form the current object
  231. */
  232. public function addButtonClass($type, $class) {
  233. $this->buttonClasses[$type][] = trim($class);
  234. $this->buttonClasses[$type] = array_unique($this->buttonClasses[$type]);
  235. return $this;
  236. }
  237. /**
  238. * Render the form
  239. *
  240. * Renders the form and returns its content.
  241. *
  242. * @param boolean $omitFormTag set this to true if you want to use your own <form> tag
  243. * @return string the generated XHTML
  244. */
  245. public function render($omitFormTag = false) {
  246. return $this->renderView('form.phtml', array('form' => $this, 'omitFormTag' => $omitFormTag));
  247. }
  248. /**
  249. * Remove all elements
  250. *
  251. * This method will remove all fieldsets from the form and reset the active
  252. * fieldset to 'none'. This will make any add* method create a new fieldset
  253. * when called.
  254. *
  255. * @return sly_Form the current object
  256. */
  257. public function clearElements() {
  258. $this->fieldsets = array();
  259. $this->currentFieldset = null;
  260. return $this;
  261. }
  262. /**
  263. * Sets the focus
  264. *
  265. * This method sets the focus to one element, generating a bit of jQuery code
  266. * to set the cursor to it when the form is rendered.
  267. *
  268. * @param mixed $element the instance or ID of the element to focus
  269. * @return sly_Form the current object
  270. */
  271. public function setFocus($element) {
  272. $this->focussedElement = $element;
  273. return $this;
  274. }
  275. /**
  276. * Get the current fieldset
  277. *
  278. * @return sly_Form_Fieldset the current fieldset (or null after the form has been created or cleared)
  279. */
  280. public function getCurrentFieldset() {
  281. return $this->currentFieldset;
  282. }
  283. /**
  284. * Get all fieldsets
  285. *
  286. * @return array list of all fieldsets
  287. */
  288. public function getFieldsets() {
  289. return $this->fieldsets;
  290. }
  291. /**
  292. * Get element by name
  293. *
  294. * @param string $name the element's name
  295. * @return sly_Form_IElement the found element or null
  296. */
  297. public function findElementByName($name) {
  298. return $this->findElement('name', $name);
  299. }
  300. /**
  301. * Get element by ID
  302. *
  303. * @param string $name the element's ID
  304. * @return sly_Form_IElement the found element or null
  305. */
  306. public function findElementByID($id) {
  307. return $this->findElement('id', $id);
  308. }
  309. /**
  310. * Get element by name
  311. *
  312. * @param string $criterium 'id' or 'name'
  313. * @param string $value the value to find
  314. * @return sly_Form_IElement the found element or null
  315. */
  316. protected function findElement($criterium, $value) {
  317. foreach ($this->fieldsets as $fieldset) {
  318. foreach ($fieldset->getRows() as $row) {
  319. foreach ($row as $element) {
  320. if ($element instanceof sly_Form_IElement) {
  321. if ($criterium === 'name' && $element->getName() === $value) return $element;
  322. if ($criterium === 'id' && $element->getID() === $value) return $element;
  323. }
  324. }
  325. }
  326. }
  327. return null;
  328. }
  329. /**
  330. * Replace an existing element
  331. *
  332. * @param string $criterium 'id' or 'name'
  333. * @param string $value the value to find
  334. * @param sly_Form_IElement the new element
  335. * @return sly_Form_IElement the replaced element or null if not found
  336. */
  337. public function replaceElement($criterium, $value, sly_Form_IElement $element) {
  338. foreach ($this->fieldsets as $fIdx => $fieldset) {
  339. foreach ($fieldset->getRows() as $rowIdx => $row) {
  340. foreach ($row as $elemIdx => $elem) {
  341. if ($elem instanceof sly_Form_IElement) {
  342. if (
  343. ($criterium === 'name' && $elem->getName() === $value) ||
  344. ($criterium === 'id' && $elem->getID() === $value)
  345. ) {
  346. return $fieldset->replaceElement($rowIdx, $elemIdx, $element);
  347. }
  348. }
  349. }
  350. }
  351. }
  352. return null;
  353. }
  354. /**
  355. * Add a new class to the form
  356. *
  357. * This method will add a CSS class to the form tag. You can give mutliple
  358. * classes at once, the method will split them up and add them one at a time,
  359. * ensuring that they are unique.
  360. *
  361. * @param string $class the CSS class
  362. * @return sly_Form the current object
  363. */
  364. public function addClass($class) {
  365. $class = explode(' ', $class);
  366. foreach ($class as $c) $this->classes[] = $c;
  367. $this->classes = array_unique($this->classes);
  368. return $this;
  369. }
  370. /**
  371. * Remove all classes
  372. *
  373. * This method removes all set CSS classes for this form.
  374. *
  375. * @return sly_Form the current object
  376. */
  377. public function clearClasses() {
  378. $this->classes = array();
  379. return $this;
  380. }
  381. /**
  382. * Get all classes
  383. *
  384. * @return array the list of CSS classes for this form
  385. */
  386. public function getClasses() {
  387. return $this->classes;
  388. }
  389. }