1: <?php
2:
3: /**
4: * This file is part of the Nette Framework (https://nette.org)
5: * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6: */
7:
8: namespace Nette\Application\UI;
9:
10: use Nette;
11:
12:
13: /**
14: * Web form adapted for Presenter.
15: */
16: class Form extends Nette\Forms\Form implements ISignalReceiver
17: {
18: /** @var callable[] function (self $sender); Occurs when form is attached to presenter */
19: public $onAnchor;
20:
21: /**
22: * Application form constructor.
23: */
24: public function __construct(Nette\ComponentModel\IContainer $parent = NULL, $name = NULL)
25: {
26: parent::__construct();
27: if ($parent !== NULL) {
28: $parent->addComponent($this, $name);
29: }
30: }
31:
32:
33: /**
34: * @return void
35: */
36: protected function validateParent(Nette\ComponentModel\IContainer $parent)
37: {
38: parent::validateParent($parent);
39: $this->monitor(Presenter::class);
40: }
41:
42:
43: /**
44: * Returns the presenter where this component belongs to.
45: * @param bool throw exception if presenter doesn't exist?
46: * @return Presenter|NULL
47: */
48: public function getPresenter($need = TRUE)
49: {
50: return $this->lookup(Presenter::class, $need);
51: }
52:
53:
54: /**
55: * This method will be called when the component (or component's parent)
56: * becomes attached to a monitored object. Do not call this method yourself.
57: * @param Nette\ComponentModel\IComponent
58: * @return void
59: */
60: protected function attached($presenter)
61: {
62: if ($presenter instanceof Presenter) {
63: if (!isset($this->getElementPrototype()->id)) {
64: $this->getElementPrototype()->id = 'frm-' . $this->lookupPath(Presenter::class);
65: }
66: if (!$this->getAction()) {
67: $this->setAction(new Link($presenter, 'this'));
68: }
69:
70: $controls = $this->getControls();
71: if (iterator_count($controls) && $this->isSubmitted()) {
72: foreach ($controls as $control) {
73: if (!$control->isDisabled()) {
74: $control->loadHttpData();
75: }
76: }
77: }
78:
79: $this->onAnchor($this);
80: }
81: parent::attached($presenter);
82: }
83:
84:
85: /**
86: * Tells if the form is anchored.
87: * @return bool
88: */
89: public function isAnchored()
90: {
91: return (bool) $this->getPresenter(FALSE);
92: }
93:
94:
95: /**
96: * Internal: returns submitted HTTP data or NULL when form was not submitted.
97: * @return array|NULL
98: */
99: protected function receiveHttpData()
100: {
101: $presenter = $this->getPresenter();
102: if (!$presenter->isSignalReceiver($this, 'submit')) {
103: return;
104: }
105:
106: $request = $presenter->getRequest();
107: if ($request->isMethod('forward') || $request->isMethod('post') !== $this->isMethod('post')) {
108: return;
109: }
110:
111: if ($this->isMethod('post')) {
112: return Nette\Utils\Arrays::mergeTree($request->getPost(), $request->getFiles());
113: } else {
114: return $request->getParameters();
115: }
116: }
117:
118:
119: protected function beforeRender()
120: {
121: parent::beforeRender();
122: $key = ($this->isMethod('post') ? '_' : '') . Presenter::SIGNAL_KEY;
123: if (!isset($this[$key])) {
124: $do = $this->lookupPath(Presenter::class) . self::NAME_SEPARATOR . 'submit';
125: $this[$key] = (new Nette\Forms\Controls\HiddenField($do))->setOmitted()->setHtmlId(FALSE);
126: }
127: }
128:
129:
130: /********************* interface ISignalReceiver ****************d*g**/
131:
132:
133: /**
134: * This method is called by presenter.
135: * @param string
136: * @return void
137: */
138: public function signalReceived($signal)
139: {
140: if ($signal === 'submit') {
141: if (!$this->getPresenter()->getRequest()->hasFlag(Nette\Application\Request::RESTORED)) {
142: $this->fireEvents();
143: }
144: } else {
145: $class = get_class($this);
146: throw new BadSignalException("Missing handler for signal '$signal' in $class.");
147: }
148: }
149:
150: }
151: