Completed
Push — wip/steps ( a89def...4fedf8 )
by Romain
02:24
created

FormController::resetSubstepsLevel()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
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;
15
16
use Exception;
17
use Romm\Formz\Controller\Processor\ControllerProcessor;
18
use Romm\Formz\Core\Core;
19
use Romm\Formz\Form\FormObject\FormObject;
20
use Romm\Formz\Form\FormObject\FormObjectFactory;
21
use Romm\Formz\Middleware\Processor\MiddlewareProcessor;
22
use Romm\Formz\Middleware\Request\Exception\ForwardException;
23
use Romm\Formz\Middleware\Request\Exception\RedirectException;
24
use Romm\Formz\Middleware\Request\Exception\StopPropagationException;
25
use Throwable;
26
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
27
use TYPO3\CMS\Extbase\Mvc\Exception\StopActionException;
28
29
/**
30
 * This is the main form controller, which is called before a controller action
31
 * with at least form argument is called.
32
 *
33
 * It will process the argument form(s), for instance by calling all its
34
 * middlewares. It allows manipulating the request, and information about the
35
 * form, before the actual action is called.
36
 */
37
class FormController extends ActionController
38
{
39
    /**
40
     * @var ControllerProcessor
41
     */
42
    protected $processor;
43
44
    /**
45
     * Main action used to dispatch the request properly, depending on FormZ
46
     * configuration.
47
     *
48
     * The request is based on the previously called controller action, and is
49
     * used to list which forms are handled (every argument of the action method
50
     * that implements the interface `FormInterface`).
51
     *
52
     * Middlewares will be called for each form argument, and may modify the
53
     * request, which is then dispatched again with modified data.
54
     *
55
     * @throws Exception
56
     */
57
    public function processFormAction()
58
    {
59
        $exception = null;
60
61
        try {
62
            $this->invokeMiddlewares();
63
            $this->manageRequestResult();
64
        } catch (Exception $exception) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
65
        } catch (Throwable $exception) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
Bug introduced by
The class Throwable does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
66
        }
67
68
        $this->persistForms();
69
70
        if ($exception) {
71
            if ($exception instanceof StopPropagationException) {
72
                if ($exception instanceof RedirectException) {
73
                    $this->redirectFromException($exception);
74
                } elseif (false === $exception instanceof ForwardException) {
75
                    $this->resetSubstepsLevel();
76
                    $this->forwardToReferrer();
77
                }
78
            } elseif ($this->processor->hasExceptionCallback()) {
79
                call_user_func($this->processor->getExceptionCallback(), $exception);
80
            } else {
81
                throw $exception;
82
            }
83
        }
84
85
        $this->continueRequest();
86
    }
87
88
    /**
89
     * @param FormObject $formObject
90
     */
91
    public function formObjectErrorAction(FormObject $formObject)
92
    {
93
        $this->view->assign('formObject', $formObject);
94
    }
95
96
    /**
97
     * Will fetch every form argument for this request, and dispatch every
98
     * middleware that was registered in its TypoScript configuration.
99
     */
100
    protected function invokeMiddlewares()
101
    {
102
        foreach ($this->processor->getRequestForms() as $formObject) {
103
            /** @var MiddlewareProcessor $middlewareProcessor */
104
            $middlewareProcessor = Core::instantiate(MiddlewareProcessor::class, $formObject, $this->processor);
105
106
            $middlewareProcessor->run();
107
        }
108
    }
109
110
    /**
111
     * @todo
112
     */
113
    protected function resetSubstepsLevel()
114
    {
115
        foreach ($this->processor->getRequestForms() as $formObject) {
116
            $stepService = FormObjectFactory::get()->getStepService($formObject);
117
            $stepService->setSubstepsLevel(1);
118
        }
119
    }
120
121
    /**
122
     * Will check if the request result contains error; if errors are found, the
123
     * request is forwarded to the referring request, with the arguments of the
124
     * current request.
125
     */
126
    protected function manageRequestResult()
127
    {
128
        $result = $this->processor->getRequest()->getOriginalRequestMappingResults();
129
        $this->request->setOriginalRequestMappingResults($result);
130
131
        if ($result->hasErrors()) {
132
            $this->forwardToReferrer();
133
        }
134
    }
135
136
    /**
137
     * Loops on every form of this request, and persists each one.
138
     */
139
    protected function persistForms()
140
    {
141
        foreach ($this->processor->getRequestForms() as $formObject) {
142
            if ($formObject->hasForm()
143
                && ($formObject->isPersistent()
144
                    || $formObject->formWasSubmitted()
145
                )
146
            ) {
147
                $formObject->getPersistenceManager()->save();
148
149
                if ($formObject->isPersistent()) {
150
                    $formObject->getFormMetadata()->persist();
151
                }
152
            }
153
        }
154
    }
155
156
    /**
157
     * Forwards the request to the original request that led to this controller.
158
     *
159
     * @throws StopActionException
160
     */
161
    protected function continueRequest()
162
    {
163
        $this->request->setDispatched(false);
164
        $request = $this->processor->getRequest();
165
166
        $this->request->setPluginName($request->getPluginName());
167
        $this->request->setControllerVendorName($request->getControllerVendorName());
168
        $this->request->setControllerExtensionName($request->getControllerExtensionName());
169
        $this->request->setControllerName($request->getControllerName());
170
        $this->request->setControllerActionName($request->getControllerActionName());
171
        $this->request->setArguments($this->processor->getRequest()->getArguments());
172
173
        throw new StopActionException;
174
    }
175
176
    /**
177
     * Forwards to the referrer request. It will also fill the arguments of the
178
     * action with the ones from the source request.
179
     *
180
     * @throws StopActionException
181
     */
182
    protected function forwardToReferrer()
183
    {
184
        $originalRequest = $this->processor->getRequest();
185
        $referringRequest = $originalRequest->getReferringRequest();
186
187
        if ($referringRequest) {
188
            $this->request->setDispatched(false);
189
190
            $this->request->setControllerVendorName($referringRequest->getControllerVendorName());
191
            $this->request->setControllerExtensionName($referringRequest->getControllerExtensionName());
192
            $this->request->setControllerName($referringRequest->getControllerName());
193
            $this->request->setControllerActionName($referringRequest->getControllerActionName());
194
            $this->request->setArguments($this->processor->getRequest()->getArguments());
195
            throw new StopActionException;
196
        } else {
197
            /**
198
             * @todo ?
199
             * @see \TYPO3\CMS\Extbase\Mvc\Controller\ActionController::forwardToReferringRequest()
200
             */
201
        }
202
203
    }
204
205
    /**
206
     * @param RedirectException $redirectException
207
     */
208
    protected function redirectFromException(RedirectException $redirectException)
209
    {
210
        $this->uriBuilder->setRequest($this->processor->getRequest());
211
212
        $this->redirect(
213
            $redirectException->getActionName(),
214
            $redirectException->getControllerName(),
215
            $redirectException->getExtensionName(),
216
            $redirectException->getArguments(),
217
            $redirectException->getPageUid(),
218
            $redirectException->getDelay(),
219
            $redirectException->getStatusCode()
220
        );
221
    }
222
223
    /**
224
     * @param ControllerProcessor $processor
225
     */
226
    public function injectProcessor(ControllerProcessor $processor)
227
    {
228
        $this->processor = $processor;
229
    }
230
}
231