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