Completed
Push — middleware-wip ( 7e7b3d...2c3646 )
by Romain
02:25
created

MiddlewareState::getResult()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
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\FormzControllerContext;
17
use Romm\Formz\Error\FormResult;
18
use Romm\Formz\Form\FormObject;
19
use Romm\Formz\Middleware\Items\Begin\BeginMiddleware;
20
use Romm\Formz\Middleware\Items\End\EndMiddleware;
21
use Romm\Formz\Middleware\MiddlewareInterface;
22
use Romm\Formz\Middleware\Signal\After;
23
use Romm\Formz\Middleware\Signal\Before;
24
use Romm\Formz\Middleware\Signal\SendsMiddlewareSignal;
25
use TYPO3\CMS\Extbase\Mvc\Controller\Arguments;
26
use TYPO3\CMS\Extbase\Mvc\Web\Request;
27
28
/**
29
 * @todo: loop on middlewares and detect which ones are using signals that wont
30
 * be processed. This should probably be a validator put on:
31
 *      \Romm\Formz\Configuration\Form\Form::$middlewares
32
 */
33
class MiddlewareState
34
{
35
    /**
36
     * @var MiddlewareInterface[]
37
     */
38
    protected $list = [];
39
40
    /**
41
     * @var FormObject
42
     */
43
    protected $formObject;
44
45
    /**
46
     * @var FormResult
47
     */
48
    protected $result;
49
50
    /**
51
     * @var Request
52
     */
53
    protected $request;
54
55
    /**
56
     * @var Arguments
57
     */
58
    protected $arguments;
59
60
    /**
61
     * @see getSignalSortedMiddlewares()
62
     *
63
     * @var array
64
     */
65
    protected $signalSortedMiddlewares = [];
66
67
    /**
68
     * @param FormObject             $formObject
69
     * @param FormzControllerContext $formzControllerContext
70
     */
71
    public function __construct(FormObject $formObject, FormzControllerContext $formzControllerContext)
72
    {
73
        $this->formObject = $formObject;
74
        $this->request = $formzControllerContext->getRequest();
75
        $this->arguments = $formzControllerContext->getArguments();
76
77
        foreach ($this->formObject->getConfiguration()->getMiddlewares() as $middleware) {
78
            $this->list[] = $middleware;
79
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
     * Will dispatch the before-signal from a given source to all middlewares
102
     * bound to the signal.
103
     *
104
     * @param SendsMiddlewareSignal $source
105
     */
106
    public function dispatchBeforeSignal(SendsMiddlewareSignal $source)
107
    {
108
        $signalName = $source->getSignalName();
109
110
        foreach ($this->getMiddlewaresBoundToSignal($signalName) as $middleware) {
111
            if ($middleware instanceof Before) {
112
                $middleware->before();
113
            }
114
        }
115
    }
116
117
    /**
118
     * Will dispatch the after-signal from a given source to all middlewares
119
     * bound to the signal.
120
     *
121
     * @param SendsMiddlewareSignal $source
122
     */
123
    public function dispatchAfterSignal(SendsMiddlewareSignal $source)
124
    {
125
        $signalName = $source->getSignalName();
126
127
        foreach ($this->getMiddlewaresBoundToSignal($signalName) as $middleware) {
128
            if ($middleware instanceof After) {
129
                $middleware->after();
130
            }
131
        }
132
    }
133
134
    /**
135
     * Returns the sorted list of middlewares bound to the given signal name.
136
     *
137
     * @param string $signalName
138
     * @return array
139
     */
140
    protected function getMiddlewaresBoundToSignal($signalName)
141
    {
142
        $signalSortedMiddlewares = $this->getSignalSortedMiddlewares();
143
144
        return (isset($signalSortedMiddlewares[$signalName]))
145
            ? $signalSortedMiddlewares[$signalName]
146
            : [];
147
    }
148
149
    /**
150
     * Returns a sorted list of the registered middlewares: the first level is
151
     * the signal used by the group, and the second level is the group of
152
     * middlewares, sorted by descendant priority of each middleware.
153
     *
154
     * @return array
155
     */
156
    protected function getSignalSortedMiddlewares()
157
    {
158
        if (empty($this->signalSortedMiddlewares)) {
159
            $this->signalSortedMiddlewares = [];
160
            $middlewareList = [];
161
162
            foreach ($this->list as $middleware) {
163
                $signal = $middleware->getBoundSignalName();
164
165
                if (false === isset($middlewareList[$signal])) {
166
                    $middlewareList[$signal] = [];
167
                }
168
169
                $middlewareList[$signal][] = $middleware;
170
            }
171
172
            foreach ($middlewareList as $key => $list) {
173
                $this->signalSortedMiddlewares[$key] = $this->sortMiddlewaresListByPriority($list);
174
            }
175
        }
176
177
        return $this->signalSortedMiddlewares;
178
    }
179
180
    /**
181
     * Will sort and return a middlewares list based on the priority of each
182
     * middleware. The middlewares with the highest priority will be placed at
183
     * the top of the list.
184
     *
185
     * @param array $list
186
     * @return array
187
     */
188
    private function sortMiddlewaresListByPriority(array $list)
189
    {
190
        usort($list, function (MiddlewareInterface $a, MiddlewareInterface $b) {
191
            $priorityA = (int)$a->getPriority();
192
            $priorityB = (int)$b->getPriority();
193
194
            if ($priorityA === $priorityB) {
195
                return 0;
196
            }
197
198
            return $priorityA < $priorityB
199
                ? 1
200
                : -1;
201
        });
202
203
        return $list;
204
    }
205
206
    /**
207
     * @return FormObject
208
     */
209
    public function getFormObject()
210
    {
211
        return $this->formObject;
212
    }
213
214
    /**
215
     * @return FormResult
216
     */
217
    public function getResult()
218
    {
219
        if (null === $this->result) {
220
            $this->result = new FormResult;
221
        }
222
223
        return $this->result;
224
    }
225
226
    /**
227
     * @return Request
228
     */
229
    public function getRequest()
230
    {
231
        return $this->request;
232
    }
233
234
    /**
235
     * @return Arguments
236
     */
237
    public function getArguments()
238
    {
239
        return $this->arguments;
240
    }
241
}
242