Completed
Push — middleware-wip ( 844477...d1e0ab )
by Romain
02:47
created

MiddlewareState::getRequestArguments()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
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\Middleware\State;
15
16
use Romm\Formz\Controller\ControllerState;
17
use Romm\Formz\Error\FormResult;
18
use Romm\Formz\Form\FormObject;
19
use Romm\Formz\Middleware\Item\Begin\BeginMiddleware;
20
use Romm\Formz\Middleware\Item\End\EndMiddleware;
21
use Romm\Formz\Middleware\MiddlewareInterface;
22
use TYPO3\CMS\Extbase\Mvc\Controller\Arguments;
23
use TYPO3\CMS\Extbase\Mvc\Web\Request;
24
25
/**
26
 * @todo: loop on middlewares and detect which ones are using signals that wont
27
 * be processed. This should probably be a validator put on:
28
 *      \Romm\Formz\Configuration\Form\Form::$middlewares
29
 */
30
class MiddlewareState
31
{
32
    /**
33
     * @var MiddlewareInterface[]
34
     */
35
    protected $list = [];
36
37
    /**
38
     * @var FormObject
39
     */
40
    protected $formObject;
41
42
    /**
43
     * @var ControllerState
44
     */
45
    protected $controllerState;
46
47
    /**
48
     * @var FormResult
49
     */
50
    protected $result;
51
52
    /**
53
     * @see getSignalSortedMiddlewares()
54
     *
55
     * @var array
56
     */
57
    protected $signalSortedMiddlewares = [];
58
59
    /**
60
     * This context is activated when the request is validating a single field
61
     * and not the whole form. In this case, special behaviours may occur, and
62
     * the state instance should be aware of it.
63
     *
64
     * @see \Romm\Formz\Middleware\State\RemoveFromSingleFieldValidationContext
65
     *
66
     * @var bool
67
     */
68
    protected $singleFieldValidationContext = false;
69
70
    /**
71
     * @param FormObject      $formObject
72
     * @param ControllerState $controllerState
73
     */
74
    public function __construct(FormObject $formObject, ControllerState $controllerState)
75
    {
76
        $this->formObject = $formObject;
77
        $this->controllerState = $controllerState;
78
79
        foreach ($this->formObject->getConfiguration()->getMiddlewares() as $middleware) {
80
            $middleware->bindMiddlewareState($this);
81
            $middleware->initialize();
82
        }
83
    }
84
85
    /**
86
     * Will run and process trough every middleware registered for the current
87
     * form object.
88
     */
89
    public function run()
90
    {
91
        $beginMiddleware = new BeginMiddleware;
92
        $beginMiddleware->bindMiddlewareState($this);
93
        $beginMiddleware->execute();
94
95
        $endMiddleware = new EndMiddleware;
96
        $endMiddleware->bindMiddlewareState($this);
97
        $endMiddleware->execute();
98
    }
99
100
    /**
101
     * Returns the sorted list of middlewares bound to the given signal name.
102
     *
103
     * @param string $signalName
104
     * @return array
105
     */
106
    public function getMiddlewaresBoundToSignal($signalName)
107
    {
108
        $signalSortedMiddlewares = $this->getSignalSortedMiddlewares();
109
110
        return (isset($signalSortedMiddlewares[$signalName]))
111
            ? $signalSortedMiddlewares[$signalName]
112
            : [];
113
    }
114
115
    /**
116
     * Returns a sorted list of the registered middlewares: the first level is
117
     * the signal used by the group, and the second level is the group of
118
     * middlewares, sorted by descendant priority of each middleware.
119
     *
120
     * @return array
121
     */
122
    protected function getSignalSortedMiddlewares()
123
    {
124
        if (empty($this->signalSortedMiddlewares)) {
125
            $this->signalSortedMiddlewares = [];
126
            $middlewareList = [];
127
128
            foreach ($this->getFilteredMiddlewares() as $middleware) {
129
                $signal = $middleware->getBoundSignalName();
130
131
                if (false === isset($middlewareList[$signal])) {
132
                    $middlewareList[$signal] = [];
133
                }
134
135
                $middlewareList[$signal][] = $middleware;
136
            }
137
138
            foreach ($middlewareList as $key => $list) {
139
                $this->signalSortedMiddlewares[$key] = $this->sortMiddlewaresListByPriority($list);
140
            }
141
        }
142
143
        return $this->signalSortedMiddlewares;
144
    }
145
146
    /**
147
     * @return MiddlewareInterface[]
148
     */
149
    protected function getFilteredMiddlewares()
150
    {
151
        $middlewares = $this->formObject->getConfiguration()->getMiddlewares();
152
153
        if ($this->inSingleFieldValidationContext()) {
154
            foreach ($middlewares as $key => $middleware) {
155
                if ($middleware instanceof RemoveFromSingleFieldValidationContext) {
156
                    unset($middlewares[$key]);
157
                }
158
            }
159
        }
160
161
        return $middlewares;
162
    }
163
164
    /**
165
     * Will sort and return a middlewares list based on the priority of each
166
     * middleware. The middlewares with the highest priority will be placed at
167
     * the top of the list.
168
     *
169
     * @param array $list
170
     * @return array
171
     */
172
    private function sortMiddlewaresListByPriority(array $list)
173
    {
174
        usort($list, function (MiddlewareInterface $a, MiddlewareInterface $b) {
175
            $priorityA = (int)$a->getPriority();
176
            $priorityB = (int)$b->getPriority();
177
178
            if ($priorityA === $priorityB) {
179
                return 0;
180
            }
181
182
            return $priorityA < $priorityB ? 1 : -1;
183
        });
184
185
        return $list;
186
    }
187
188
    /**
189
     * @return FormObject
190
     */
191
    public function getFormObject()
192
    {
193
        return $this->formObject;
194
    }
195
196
    /**
197
     * @return FormResult
198
     */
199
    public function getResult()
200
    {
201
        if (null === $this->result) {
202
            $this->result = new FormResult;
203
        }
204
205
        return $this->result;
206
    }
207
208
    /**
209
     * @return Request
210
     */
211
    public function getRequest()
212
    {
213
        return $this->controllerState->getRequest();
214
    }
215
216
    /**
217
     * @return Arguments
218
     */
219
    public function getRequestArguments()
220
    {
221
        return $this->controllerState->getRequestArguments();
222
    }
223
224
    /**
225
     * @return array
226
     */
227
    public function getSettings()
228
    {
229
        return $this->controllerState->getSettings();
230
    }
231
232
    /**
233
     * @see $singleFieldValidationContext
234
     *
235
     * @return bool
236
     */
237
    public function inSingleFieldValidationContext()
238
    {
239
        return $this->singleFieldValidationContext;
240
    }
241
242
    /**
243
     * @see $singleFieldValidationContext
244
     */
245
    public function activateSingleFieldValidationContext()
246
    {
247
        $this->singleFieldValidationContext = true;
248
    }
249
}
250