Completed
Push — middleware-wip-tmp ( d8f2e1 )
by Romain
02:50
created

FormController::commitMetadata()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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