Completed
Push — middleware-wip ( 21e3dc...d468d0 )
by Romain
02:52
created

MiddlewareState::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 14
rs 9.4285
cc 2
eloc 9
nc 2
nop 2
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
     * @var array
62
     */
63
    protected $settings;
64
65
    /**
66
     * @see getSignalSortedMiddlewares()
67
     *
68
     * @var array
69
     */
70
    protected $signalSortedMiddlewares = [];
71
72
    /**
73
     * @param FormObject             $formObject
74
     * @param FormzControllerContext $formzControllerContext
75
     */
76
    public function __construct(FormObject $formObject, FormzControllerContext $formzControllerContext)
77
    {
78
        $this->formObject = $formObject;
79
        $this->request = $formzControllerContext->getRequest();
80
        $this->arguments = $formzControllerContext->getArguments();
81
        $this->settings = $formzControllerContext->getSettings();
82
83
        foreach ($this->formObject->getConfiguration()->getMiddlewares() as $middleware) {
84
            $this->list[] = $middleware;
85
86
            $middleware->bindMiddlewareState($this);
87
            $middleware->initialize();
88
        }
89
    }
90
91
    /**
92
     * Will run and process trough every middleware registered for the current
93
     * form object.
94
     */
95
    public function run()
96
    {
97
        $beginMiddleware = new BeginMiddleware;
98
        $beginMiddleware->bindMiddlewareState($this);
99
        $beginMiddleware->execute();
100
101
        $endMiddleware = new EndMiddleware;
102
        $endMiddleware->bindMiddlewareState($this);
103
        $endMiddleware->execute();
104
    }
105
106
    /**
107
     * Will dispatch the before-signal from a given source to all middlewares
108
     * bound to the signal.
109
     *
110
     * @param SendsMiddlewareSignal $source
111
     */
112
    public function dispatchBeforeSignal(SendsMiddlewareSignal $source)
113
    {
114
        $signalName = $source->getSignalName();
115
116
        foreach ($this->getMiddlewaresBoundToSignal($signalName) as $middleware) {
117
            if ($middleware instanceof Before) {
118
                $middleware->before();
119
            }
120
        }
121
    }
122
123
    /**
124
     * Will dispatch the after-signal from a given source to all middlewares
125
     * bound to the signal.
126
     *
127
     * @param SendsMiddlewareSignal $source
128
     */
129
    public function dispatchAfterSignal(SendsMiddlewareSignal $source)
130
    {
131
        $signalName = $source->getSignalName();
132
133
        foreach ($this->getMiddlewaresBoundToSignal($signalName) as $middleware) {
134
            if ($middleware instanceof After) {
135
                $middleware->after();
136
            }
137
        }
138
    }
139
140
    /**
141
     * Returns the sorted list of middlewares bound to the given signal name.
142
     *
143
     * @param string $signalName
144
     * @return array
145
     */
146
    protected function getMiddlewaresBoundToSignal($signalName)
147
    {
148
        $signalSortedMiddlewares = $this->getSignalSortedMiddlewares();
149
150
        return (isset($signalSortedMiddlewares[$signalName]))
151
            ? $signalSortedMiddlewares[$signalName]
152
            : [];
153
    }
154
155
    /**
156
     * Returns a sorted list of the registered middlewares: the first level is
157
     * the signal used by the group, and the second level is the group of
158
     * middlewares, sorted by descendant priority of each middleware.
159
     *
160
     * @return array
161
     */
162
    protected function getSignalSortedMiddlewares()
163
    {
164
        if (empty($this->signalSortedMiddlewares)) {
165
            $this->signalSortedMiddlewares = [];
166
            $middlewareList = [];
167
168
            foreach ($this->list as $middleware) {
169
                $signal = $middleware->getBoundSignalName();
170
171
                if (false === isset($middlewareList[$signal])) {
172
                    $middlewareList[$signal] = [];
173
                }
174
175
                $middlewareList[$signal][] = $middleware;
176
            }
177
178
            foreach ($middlewareList as $key => $list) {
179
                $this->signalSortedMiddlewares[$key] = $this->sortMiddlewaresListByPriority($list);
180
            }
181
        }
182
183
        return $this->signalSortedMiddlewares;
184
    }
185
186
    /**
187
     * Will sort and return a middlewares list based on the priority of each
188
     * middleware. The middlewares with the highest priority will be placed at
189
     * the top of the list.
190
     *
191
     * @param array $list
192
     * @return array
193
     */
194
    private function sortMiddlewaresListByPriority(array $list)
195
    {
196
        usort($list, function (MiddlewareInterface $a, MiddlewareInterface $b) {
197
            $priorityA = (int)$a->getPriority();
198
            $priorityB = (int)$b->getPriority();
199
200
            if ($priorityA === $priorityB) {
201
                return 0;
202
            }
203
204
            return $priorityA < $priorityB
205
                ? 1
206
                : -1;
207
        });
208
209
        return $list;
210
    }
211
212
    /**
213
     * @return FormObject
214
     */
215
    public function getFormObject()
216
    {
217
        return $this->formObject;
218
    }
219
220
    /**
221
     * @return FormResult
222
     */
223
    public function getResult()
224
    {
225
        if (null === $this->result) {
226
            $this->result = new FormResult;
227
        }
228
229
        return $this->result;
230
    }
231
232
    /**
233
     * @return Request
234
     */
235
    public function getRequest()
236
    {
237
        return $this->request;
238
    }
239
240
    /**
241
     * @return Arguments
242
     */
243
    public function getArguments()
244
    {
245
        return $this->arguments;
246
    }
247
248
    /**
249
     * @return array
250
     */
251
    public function getSettings()
252
    {
253
        return $this->settings;
254
    }
255
}
256