Completed
Push — wip/steps ( a8ec08...593c83 )
by Romain
02:14
created

MiddlewareProcessor::inSingleFieldValidationContext()   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\Processor;
15
16
use Romm\Formz\Controller\Processor\ControllerProcessor;
17
use Romm\Formz\Core\Core;
18
use Romm\Formz\Error\FormResult;
19
use Romm\Formz\Form\FormObject\FormObject;
20
use Romm\Formz\Middleware\Item\Begin\BeginMiddleware;
21
use Romm\Formz\Middleware\Item\End\EndMiddleware;
22
use Romm\Formz\Middleware\MiddlewareInterface;
23
use Romm\Formz\Middleware\Scope\MainScope;
24
use TYPO3\CMS\Extbase\Mvc\Controller\Arguments;
25
use TYPO3\CMS\Extbase\Mvc\Web\Request;
26
27
/**
28
 * @todo: loop on middlewares and detect which ones are using signals that wont
29
 * be processed. This should probably be a validator put on:
30
 *      \Romm\Formz\Form\Definition\Form::$middlewares
31
 */
32
class MiddlewareProcessor
33
{
34
    /**
35
     * @var FormObject
36
     */
37
    protected $formObject;
38
39
    /**
40
     * @var ControllerProcessor
41
     */
42
    protected $controllerProcessor;
43
44
    /**
45
     * @var FormResult
46
     */
47
    protected $result;
48
49
    /**
50
     * @see getSignalSortedMiddlewares()
51
     *
52
     * @var array
53
     */
54
    protected $signalSortedMiddlewares = [];
55
56
    /**
57
     * @param FormObject          $formObject
58
     * @param ControllerProcessor $controllerProcessor
59
     */
60
    public function __construct(FormObject $formObject, ControllerProcessor $controllerProcessor)
61
    {
62
        $this->formObject = $formObject;
63
        $this->controllerProcessor = $controllerProcessor;
64
    }
65
66
    /**
67
     * Will run and process trough every middleware registered for the current
68
     * form object.
69
     */
70
    public function run()
71
    {
72
        /** @var BeginMiddleware $beginMiddleware */
73
        $beginMiddleware = Core::instantiate(BeginMiddleware::class);
74
        $beginMiddleware->bindMiddlewareProcessor($this);
75
        $beginMiddleware->initialize();
76
77
        foreach ($this->formObject->getDefinition()->getAllMiddlewares() as $middleware) {
78
            $middleware->bindMiddlewareProcessor($this);
79
            $middleware->initialize();
80
        }
81
82
        $beginMiddleware->execute();
83
84
        /** @var EndMiddleware $endMiddleware */
85
        $endMiddleware = Core::instantiate(EndMiddleware::class);
86
        $endMiddleware->bindMiddlewareProcessor($this);
87
        $endMiddleware->execute();
88
    }
89
90
    /**
91
     * Returns the sorted list of middlewares bound to the given signal name.
92
     *
93
     * @param string $signalName
94
     * @return MiddlewareInterface[]
95
     */
96
    public function getMiddlewaresBoundToSignal($signalName)
97
    {
98
        $signalSortedMiddlewares = $this->getSignalSortedMiddlewares();
99
100
        return (isset($signalSortedMiddlewares[$signalName]))
101
            ? $signalSortedMiddlewares[$signalName]
102
            : [];
103
    }
104
105
    /**
106
     * Returns a sorted list of the registered middlewares: the first level is
107
     * the signal used by the group, and the second level is the group of
108
     * middlewares, sorted by descendant priority of each middleware.
109
     *
110
     * @return array
111
     */
112
    protected function getSignalSortedMiddlewares()
113
    {
114
        if (empty($this->signalSortedMiddlewares)) {
115
            $this->signalSortedMiddlewares = [];
116
            $middlewareList = [];
117
118
            foreach ($this->getScopeFilteredMiddlewares() as $middleware) {
119
                $signal = $middleware->getBoundSignalName();
120
121
                if (false === isset($middlewareList[$signal])) {
122
                    $middlewareList[$signal] = [];
123
                }
124
125
                $middlewareList[$signal][] = $middleware;
126
            }
127
128
            foreach ($middlewareList as $key => $list) {
129
                $this->signalSortedMiddlewares[$key] = $this->sortMiddlewaresListByPriority($list);
130
            }
131
        }
132
133
        return $this->signalSortedMiddlewares;
134
    }
135
136
    /**
137
     * @return MiddlewareInterface[]
138
     */
139
    protected function getScopeFilteredMiddlewares()
140
    {
141
        $middlewares = $this->formObject->getDefinition()->getAllMiddlewares();
142
        $scope = $this->controllerProcessor->getScope();
143
144
        foreach ($middlewares as $key => $middleware) {
145
            $scopes = $middleware->getScopes();
146
            if ($scopes->isBlackListed($scope)
147
                || (false === $scopes->isWhiteListed($scope)
148
                    && false === $scopes->isWhiteListed(MainScope::class)
149
                )
150
            ) {
151
                unset($middlewares[$key]);
152
            }
153
        }
154
155
        return $middlewares;
156
    }
157
158
    /**
159
     * Will sort and return a middlewares list based on the priority of each
160
     * middleware. The middlewares with the highest priority will be placed at
161
     * the top of the list.
162
     *
163
     * @param MiddlewareInterface[] $list
164
     * @return MiddlewareInterface[]
165
     */
166
    private function sortMiddlewaresListByPriority(array $list)
167
    {
168
        usort($list, function (MiddlewareInterface $a, MiddlewareInterface $b) {
169
            $priorityA = (int)$a->getPriority();
170
            $priorityB = (int)$b->getPriority();
171
172
            if ($priorityA === $priorityB) {
173
                return 0;
174
            }
175
176
            return $priorityA < $priorityB ? 1 : -1;
177
        });
178
179
        return $list;
180
    }
181
182
    /**
183
     * @return FormObject
184
     */
185
    public function getFormObject()
186
    {
187
        return $this->formObject;
188
    }
189
190
    /**
191
     * @return Request
192
     */
193
    public function getRequest()
194
    {
195
        return $this->controllerProcessor->getRequest();
196
    }
197
198
    /**
199
     * @return Arguments
200
     */
201
    public function getRequestArguments()
202
    {
203
        return $this->controllerProcessor->getRequestArguments();
204
    }
205
206
    /**
207
     * @return array
208
     */
209
    public function getSettings()
210
    {
211
        return $this->controllerProcessor->getSettings();
212
    }
213
}
214