Completed
Push — middleware-wip ( a395c5...d52214 )
by Romain
03:54
created

MiddlewareProcessor   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 205
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 6

Importance

Changes 0
Metric Value
wmc 23
lcom 2
cbo 6
dl 0
loc 205
rs 10
c 0
b 0
f 0

12 Methods

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