Completed
Push — feature/middleware ( 180b74...67e214 )
by Romain
04:26
created

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