PageRenderTime 47ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/www/libs/nette-dev/Forms/FormContainer.php

https://github.com/bazo/Mokuji
PHP | 478 lines | 185 code | 106 blank | 187 comment | 24 complexity | 663703b4e4bf6722ea838aced47b9054 MD5 | raw file
Possible License(s): BSD-3-Clause, MIT
  1. <?php
  2. /**
  3. * Nette Framework
  4. *
  5. * @copyright Copyright (c) 2004, 2010 David Grudl
  6. * @license http://nettephp.com/license Nette license
  7. * @link http://nettephp.com
  8. * @category Nette
  9. * @package Nette\Forms
  10. */
  11. /**
  12. * Container for form controls.
  13. *
  14. * @copyright Copyright (c) 2004, 2010 David Grudl
  15. * @package Nette\Forms
  16. *
  17. * @property-read ArrayIterator $controls
  18. * @property-read Form $form
  19. * @property-read bool $valid
  20. * @property array $values
  21. */
  22. class FormContainer extends ComponentContainer implements ArrayAccess, INamingContainer
  23. {
  24. /** @var array of function(Form $sender); Occurs when the form is validated */
  25. public $onValidate;
  26. /** @var FormGroup */
  27. protected $currentGroup;
  28. /** @var bool */
  29. protected $valid;
  30. /********************* data exchange ****************d*g**/
  31. /**
  32. * Fill-in with default values.
  33. * @param array|Traversable values used to fill the form
  34. * @param bool erase other default values?
  35. * @return FormContainer provides a fluent interface
  36. */
  37. public function setDefaults($values, $erase = FALSE)
  38. {
  39. $form = $this->getForm(FALSE);
  40. if (!$form || !$form->isAnchored() || !$form->isSubmitted()) {
  41. $this->setValues($values, $erase);
  42. }
  43. return $this;
  44. }
  45. /**
  46. * Fill-in with values.
  47. * @param array|Traversable values used to fill the form
  48. * @param bool erase other controls?
  49. * @return FormContainer provides a fluent interface
  50. */
  51. public function setValues($values, $erase = FALSE)
  52. {
  53. if ($values instanceof Traversable) {
  54. $values = iterator_to_array($values);
  55. } elseif (!is_array($values)) {
  56. throw new InvalidArgumentException("Values must be an array, " . gettype($values) ." given.");
  57. }
  58. $cursor = & $values;
  59. $iterator = $this->getComponents(TRUE);
  60. foreach ($iterator as $name => $control) {
  61. $sub = $iterator->getSubIterator();
  62. if (!isset($sub->cursor)) {
  63. $sub->cursor = & $cursor;
  64. }
  65. if ($control instanceof IFormControl) {
  66. if ((is_array($sub->cursor) || $sub->cursor instanceof ArrayAccess) && array_key_exists($name, $sub->cursor)) {
  67. $control->setValue($sub->cursor[$name]);
  68. } elseif ($erase) {
  69. $control->setValue(NULL);
  70. }
  71. }
  72. if ($control instanceof INamingContainer) {
  73. if ((is_array($sub->cursor) || $sub->cursor instanceof ArrayAccess) && isset($sub->cursor[$name])) {
  74. $cursor = & $sub->cursor[$name];
  75. } else {
  76. unset($cursor);
  77. $cursor = NULL;
  78. }
  79. }
  80. }
  81. return $this;
  82. }
  83. /**
  84. * Returns the values submitted by the form.
  85. * @return array
  86. */
  87. public function getValues()
  88. {
  89. $values = array();
  90. $cursor = & $values;
  91. $iterator = $this->getComponents(TRUE);
  92. foreach ($iterator as $name => $control) {
  93. $sub = $iterator->getSubIterator();
  94. if (!isset($sub->cursor)) {
  95. $sub->cursor = & $cursor;
  96. }
  97. if ($control instanceof IFormControl && !$control->isDisabled() && !($control instanceof ISubmitterControl)) {
  98. $sub->cursor[$name] = $control->getValue();
  99. }
  100. if ($control instanceof INamingContainer) {
  101. $cursor = & $sub->cursor[$name];
  102. $cursor = array();
  103. }
  104. }
  105. return $values;
  106. }
  107. /********************* validation ****************d*g**/
  108. /**
  109. * Is form valid?
  110. * @return bool
  111. */
  112. public function isValid()
  113. {
  114. if ($this->valid === NULL) {
  115. $this->validate();
  116. }
  117. return $this->valid;
  118. }
  119. /**
  120. * Performs the server side validation.
  121. * @return void
  122. */
  123. public function validate()
  124. {
  125. $this->valid = TRUE;
  126. $this->onValidate($this);
  127. foreach ($this->getControls() as $control) {
  128. if (!$control->getRules()->validate()) {
  129. $this->valid = FALSE;
  130. }
  131. }
  132. }
  133. /********************* form building ****************d*g**/
  134. /**
  135. * @param FormGroup
  136. * @return FormContainer provides a fluent interface
  137. */
  138. public function setCurrentGroup(FormGroup $group = NULL)
  139. {
  140. $this->currentGroup = $group;
  141. return $this;
  142. }
  143. /**
  144. * Adds the specified component to the IComponentContainer.
  145. * @param IComponent
  146. * @param string
  147. * @param string
  148. * @return void
  149. * @throws InvalidStateException
  150. */
  151. public function addComponent(IComponent $component, $name, $insertBefore = NULL)
  152. {
  153. parent::addComponent($component, $name, $insertBefore);
  154. if ($this->currentGroup !== NULL && $component instanceof IFormControl) {
  155. $this->currentGroup->add($component);
  156. }
  157. }
  158. /**
  159. * Iterates over all form controls.
  160. * @return ArrayIterator
  161. */
  162. public function getControls()
  163. {
  164. return $this->getComponents(TRUE, 'Nette\Forms\IFormControl');
  165. }
  166. /**
  167. * Returns form.
  168. * @param bool throw exception if form doesn't exist?
  169. * @return Form
  170. */
  171. public function getForm($need = TRUE)
  172. {
  173. return $this->lookup('Nette\Forms\Form', $need);
  174. }
  175. /********************* control factories ****************d*g**/
  176. /**
  177. * Adds single-line text input control to the form.
  178. * @param string control name
  179. * @param string label
  180. * @param int width of the control
  181. * @param int maximum number of characters the user may enter
  182. * @return TextInput
  183. */
  184. public function addText($name, $label = NULL, $cols = NULL, $maxLength = NULL)
  185. {
  186. return $this[$name] = new TextInput($label, $cols, $maxLength);
  187. }
  188. /**
  189. * Adds single-line text input control used for sensitive input such as passwords.
  190. * @param string control name
  191. * @param string label
  192. * @param int width of the control
  193. * @param int maximum number of characters the user may enter
  194. * @return TextInput
  195. */
  196. public function addPassword($name, $label = NULL, $cols = NULL, $maxLength = NULL)
  197. {
  198. $control = new TextInput($label, $cols, $maxLength);
  199. $control->setPasswordMode(TRUE);
  200. return $this[$name] = $control;
  201. }
  202. /**
  203. * Adds multi-line text input control to the form.
  204. * @param string control name
  205. * @param string label
  206. * @param int width of the control
  207. * @param int height of the control in text lines
  208. * @return TextArea
  209. */
  210. public function addTextArea($name, $label = NULL, $cols = 40, $rows = 10)
  211. {
  212. return $this[$name] = new TextArea($label, $cols, $rows);
  213. }
  214. /**
  215. * Adds control that allows the user to upload files.
  216. * @param string control name
  217. * @param string label
  218. * @return FileUpload
  219. */
  220. public function addFile($name, $label = NULL)
  221. {
  222. return $this[$name] = new FileUpload($label);
  223. }
  224. /**
  225. * Adds hidden form control used to store a non-displayed value.
  226. * @param string control name
  227. * @param mixed default value
  228. * @return HiddenField
  229. */
  230. public function addHidden($name, $default = NULL)
  231. {
  232. $control = new HiddenField;
  233. $control->setDefaultValue($default);
  234. return $this[$name] = $control;
  235. }
  236. /**
  237. * Adds check box control to the form.
  238. * @param string control name
  239. * @param string caption
  240. * @return Checkbox
  241. */
  242. public function addCheckbox($name, $caption)
  243. {
  244. return $this[$name] = new Checkbox($caption);
  245. }
  246. /**
  247. * Adds set of radio button controls to the form.
  248. * @param string control name
  249. * @param string label
  250. * @param array options from which to choose
  251. * @return RadioList
  252. */
  253. public function addRadioList($name, $label = NULL, array $items = NULL)
  254. {
  255. return $this[$name] = new RadioList($label, $items);
  256. }
  257. /**
  258. * Adds select box control that allows single item selection.
  259. * @param string control name
  260. * @param string label
  261. * @param array items from which to choose
  262. * @param int number of rows that should be visible
  263. * @return SelectBox
  264. */
  265. public function addSelect($name, $label = NULL, array $items = NULL, $size = NULL)
  266. {
  267. return $this[$name] = new SelectBox($label, $items, $size);
  268. }
  269. /**
  270. * Adds select box control that allows multiple item selection.
  271. * @param string control name
  272. * @param string label
  273. * @param array options from which to choose
  274. * @param int number of rows that should be visible
  275. * @return MultiSelectBox
  276. */
  277. public function addMultiSelect($name, $label = NULL, array $items = NULL, $size = NULL)
  278. {
  279. return $this[$name] = new MultiSelectBox($label, $items, $size);
  280. }
  281. /**
  282. * Adds button used to submit form.
  283. * @param string control name
  284. * @param string caption
  285. * @return SubmitButton
  286. */
  287. public function addSubmit($name, $caption)
  288. {
  289. return $this[$name] = new SubmitButton($caption);
  290. }
  291. /**
  292. * Adds push buttons with no default behavior.
  293. * @param string control name
  294. * @param string caption
  295. * @return Button
  296. */
  297. public function addButton($name, $caption)
  298. {
  299. return $this[$name] = new Button($caption);
  300. }
  301. /**
  302. * Adds graphical button used to submit form.
  303. * @param string control name
  304. * @param string URI of the image
  305. * @param string alternate text for the image
  306. * @return ImageButton
  307. */
  308. public function addImage($name, $src = NULL, $alt = NULL)
  309. {
  310. return $this[$name] = new ImageButton($src, $alt);
  311. }
  312. /**
  313. * Adds naming container to the form.
  314. * @param string name
  315. * @return FormContainer
  316. */
  317. public function addContainer($name)
  318. {
  319. $control = new FormContainer;
  320. $control->currentGroup = $this->currentGroup;
  321. return $this[$name] = $control;
  322. }
  323. /********************* interface \ArrayAccess ****************d*g**/
  324. /**
  325. * Adds the component to the container.
  326. * @param string component name
  327. * @param IComponent
  328. * @return void.
  329. */
  330. final public function offsetSet($name, $component)
  331. {
  332. $this->addComponent($component, $name);
  333. }
  334. /**
  335. * Returns component specified by name. Throws exception if component doesn't exist.
  336. * @param string component name
  337. * @return IComponent
  338. * @throws InvalidArgumentException
  339. */
  340. final public function offsetGet($name)
  341. {
  342. return $this->getComponent($name, TRUE);
  343. }
  344. /**
  345. * Does component specified by name exists?
  346. * @param string component name
  347. * @return bool
  348. */
  349. final public function offsetExists($name)
  350. {
  351. return $this->getComponent($name, FALSE) !== NULL;
  352. }
  353. /**
  354. * Removes component from the container. Throws exception if component doesn't exist.
  355. * @param string component name
  356. * @return void
  357. */
  358. final public function offsetUnset($name)
  359. {
  360. $component = $this->getComponent($name, FALSE);
  361. if ($component !== NULL) {
  362. $this->removeComponent($component);
  363. }
  364. }
  365. /**
  366. * Prevents cloning.
  367. */
  368. final public function __clone()
  369. {
  370. throw new NotImplementedException('Form cloning is not supported yet.');
  371. }
  372. }