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

/Nette/Forms/Container.php

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