Completed
Push — wip/steps ( 793f88...b9a1af )
by Romain
02:37
created

ControllerProcessor::doDispatch()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 14
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 9
nc 2
nop 0
1
<?php
2
/*
3
 * 2017 Romain CANON <[email protected]>
4
 *
5
 * This file is part of the TYPO3 FormZ project.
6
 * It is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU General Public License, either
8
 * version 3 of the License, or any later version.
9
 *
10
 * For the full copyright and license information, see:
11
 * http://www.gnu.org/licenses/gpl-3.0.html
12
 */
13
14
namespace Romm\Formz\Controller\Processor;
15
16
use Romm\Formz\Form\FormInterface;
17
use Romm\Formz\Form\FormObject\FormObject;
18
use Romm\Formz\Form\FormObject\FormObjectFactory;
19
use Romm\Formz\Service\Traits\ExtendedSelfInstantiateTrait;
20
use TYPO3\CMS\Core\SingletonInterface;
21
use TYPO3\CMS\Extbase\Mvc\Controller\Argument;
22
use TYPO3\CMS\Extbase\Mvc\Controller\Arguments;
23
use TYPO3\CMS\Extbase\Mvc\Exception\StopActionException;
24
use TYPO3\CMS\Extbase\Mvc\Request as MvcRequest;
25
use TYPO3\CMS\Extbase\Mvc\Web\Request;
26
27
class ControllerProcessor implements SingletonInterface
28
{
29
    use ExtendedSelfInstantiateTrait;
30
31
    /**
32
     * @var FormObjectFactory
33
     */
34
    protected $formObjectFactory;
35
36
    /**
37
     * @var FormObject[]
38
     */
39
    protected $formArguments;
40
41
    /**
42
     * @var bool
43
     */
44
    protected $dispatched = false;
45
46
    /**
47
     * @var Request
48
     */
49
    protected $originalRequest;
50
51
    /**
52
     * @var Request
53
     */
54
    protected $request;
55
56
    /**
57
     * @var Arguments
58
     */
59
    protected $requestArguments;
60
61
    /**
62
     * @var array
63
     */
64
    protected $settings = [];
65
66
    /**
67
     * @todo
68
     *
69
     * @var string
70
     */
71
    protected $lastDispatchedRequest;
72
73
    /**
74
     * @param MvcRequest $request
75
     * @param Arguments  $requestArguments
76
     * @param array      $settings
77
     * @return $this
78
     */
79
    public static function prepare(MvcRequest $request, Arguments $requestArguments, array $settings)
80
    {
81
        return self::get()->setData($request, $requestArguments, $settings);
82
    }
83
84
    /**
85
     * Injects the data needed for this class to work properly. This method must
86
     * be called before the dispatch is called.
87
     *
88
     * @param MvcRequest $request
89
     * @param Arguments  $requestArguments
90
     * @param array      $settings
91
     * @return $this
92
     */
93
    public function setData(MvcRequest $request, Arguments $requestArguments, array $settings)
94
    {
95
        /** @var Request $request */
96
        $dispatchedRequest = $request->getControllerObjectName() . '::' . $request->getControllerActionName();
97
98
        if ($dispatchedRequest !== $this->lastDispatchedRequest) {
99
            $this->lastDispatchedRequest = $dispatchedRequest;
100
101
            $this->originalRequest = $request;
102
            $this->request = clone $request;
103
            $this->requestArguments = $requestArguments;
104
            $this->settings = $settings;
105
            $this->formArguments = null;
0 ignored issues
show
Documentation Bug introduced by
It seems like null of type null is incompatible with the declared type array<integer,object<Rom...FormObject\FormObject>> of property $formArguments.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
106
            $this->dispatched = false;
107
        }
108
109
        return $this;
110
    }
111
112
    /**
113
     * Will dispatch the current request to the form controller, which will take
114
     * care of processing everything properly.
115
     *
116
     * In case no form is found in the controller action parameters, the current
117
     * request is not killed.
118
     *
119
     * @throws StopActionException
120
     */
121
    public function dispatch()
122
    {
123
        if (false === $this->dispatched) {
124
            $this->dispatched = true;
125
126
            $this->doDispatch();
127
        }
128
    }
129
130
    /**
131
     * Wrapper for unit testing.
132
     */
133
    protected function doDispatch()
134
    {
135
        if (false === empty($this->getRequestForms())) {
136
            $this->originalRequest->setDispatched(false);
137
            $this->originalRequest->setControllerVendorName('Romm');
138
            $this->originalRequest->setControllerExtensionName('Formz');
139
            $this->originalRequest->setControllerName('Form');
140
            $this->originalRequest->setControllerActionName('processForm');
141
142
            $this->checkFormObjectsErrors();
143
144
            throw new StopActionException;
145
        }
146
    }
147
148
    /**
149
     * Will check if the form objects found in the request arguments contain
150
     * configuration errors. If they do, we dispatch the request to the error
151
     * view, where all errors will be explained properly to the user.
152
     */
153
    protected function checkFormObjectsErrors()
154
    {
155
        foreach ($this->getRequestForms() as $formObject) {
156
            if ($formObject->getDefinitionValidationResult()->hasErrors()) {
157
                $this->originalRequest->setControllerActionName('formObjectError');
158
                $this->originalRequest->setArguments(['formObject' => $formObject]);
159
160
                break;
161
            }
162
        }
163
    }
164
165
    /**
166
     * Loops on the request arguments, and pick up each one that is a form
167
     * instance (it implements `FormInterface`).
168
     *
169
     * @return FormObject[]
170
     */
171
    public function getRequestForms()
172
    {
173
        if (null === $this->formArguments) {
174
            $this->formArguments = [];
175
176
            /** @var Argument $argument */
177
            foreach ($this->requestArguments as $argument) {
178
                $type = $argument->getDataType();
179
180
                if (class_exists($type)
181
                    && in_array(FormInterface::class, class_implements($type))
182
                ) {
183
                    $formClassName = $argument->getDataType();
184
                    $formName = $argument->getName();
185
186
                    $formObject = $this->formObjectFactory->getInstanceWithClassName($formClassName, $formName);
187
                    $this->formArguments[$formName] = $formObject;
188
                }
189
            }
190
        }
191
192
        return $this->formArguments;
193
    }
194
195
    /**
196
     * @return Request
197
     */
198
    public function getRequest()
199
    {
200
        return $this->request;
201
    }
202
203
    /**
204
     * @return Arguments
205
     */
206
    public function getRequestArguments()
207
    {
208
        return $this->requestArguments;
209
    }
210
211
    /**
212
     * @return array
213
     */
214
    public function getSettings()
215
    {
216
        return $this->settings;
217
    }
218
219
    /**
220
     * @param FormObjectFactory $formObjectFactory
221
     */
222
    public function injectFormObjectFactory(FormObjectFactory $formObjectFactory)
223
    {
224
        $this->formObjectFactory = $formObjectFactory;
225
    }
226
}
227