Completed
Push — middleware-wip ( 106169...2ebda9 )
by Romain
02:43
created

MiddlewareState::sendBeforeSignal()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 6
nc 1
nop 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\State;
15
16
use Romm\Formz\Controller\FormzControllerContext;
17
use Romm\Formz\Form\FormObject;
18
use Romm\Formz\Middleware\Items\Begin\BeginMiddleware;
19
use Romm\Formz\Middleware\Items\End\EndMiddleware;
20
use Romm\Formz\Middleware\MiddlewareInterface;
21
use Romm\Formz\Middleware\Signal\After;
22
use Romm\Formz\Middleware\Signal\Before;
23
use Romm\Formz\Middleware\Signal\SendsMiddlewareSignal;
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\Configuration\Form\Form::$middlewares
31
 */
32
class MiddlewareState
33
{
34
    /**
35
     * @var MiddlewareInterface[]
36
     */
37
    protected $list = [];
38
39
    /**
40
     * @var FormObject
41
     */
42
    protected $formObject;
43
44
    /**
45
     * @var Request
46
     */
47
    protected $request;
48
49
    /**
50
     * @var Arguments
51
     */
52
    protected $requestArguments;
53
54
    /**
55
     * @see getSignalSortedMiddlewares()
56
     *
57
     * @var array
58
     */
59
    protected $signalSortedMiddlewares = [];
60
61
    /**
62
     * @param FormObject             $formObject
63
     * @param FormzControllerContext $formzControllerContext
64
     */
65
    public function __construct(FormObject $formObject, FormzControllerContext $formzControllerContext)
66
    {
67
        $this->formObject = $formObject;
68
        $this->request = $formzControllerContext->getRequest();
69
        $this->requestArguments = $formzControllerContext->getArguments();
70
71
        foreach ($this->formObject->getConfiguration()->getMiddlewares() as $middleware) {
72
            $middleware->attachMiddlewareState($this);
73
            $this->list[] = $middleware;
74
        }
75
    }
76
77
    /**
78
     * Will run and process trough every middleware registered for the current
79
     * form object.
80
     */
81
    public function run()
82
    {
83
        $beginMiddleware = new BeginMiddleware;
84
        $beginMiddleware->attachMiddlewareState($this);
85
        $beginMiddleware->execute();
86
87
        $endMiddleware = new EndMiddleware;
88
        $endMiddleware->attachMiddlewareState($this);
89
        $endMiddleware->execute();
90
    }
91
92
    /**
93
     * Will dispatch the before-signal from a given source to all middlewares
94
     * attached to the signal.
95
     *
96
     * @param SendsMiddlewareSignal $source
97
     */
98
    public function dispatchBeforeSignal(SendsMiddlewareSignal $source)
99
    {
100
        $signalName = $source->getSignalName();
101
102
        foreach ($this->getMiddlewaresAttachedToSignal($signalName) as $middleware) {
103
            if ($middleware instanceof Before) {
104
                $middleware->before();
105
            }
106
        }
107
    }
108
109
    /**
110
     * Will dispatch the after-signal from a given source to all middlewares
111
     * attached to the signal.
112
     *
113
     * @param SendsMiddlewareSignal $source
114
     */
115
    public function dispatchAfterSignal(SendsMiddlewareSignal $source)
116
    {
117
        $signalName = $source->getSignalName();
118
119
        foreach ($this->getMiddlewaresAttachedToSignal($signalName) as $middleware) {
120
            if ($middleware instanceof After) {
121
                $middleware->after();
122
            }
123
        }
124
    }
125
126
    /**
127
     * Returns the sorted list of middlewares attached to the given signal name.
128
     *
129
     * @param string $signalName
130
     * @return array
131
     */
132
    protected function getMiddlewaresAttachedToSignal($signalName)
133
    {
134
        $signalSortedMiddlewares = $this->getSignalSortedMiddlewares();
135
136
        return (isset($signalSortedMiddlewares[$signalName]))
137
            ? $signalSortedMiddlewares[$signalName]
138
            : [];
139
    }
140
141
    /**
142
     * Returns a sorted list of the registered middlewares: the first level is
143
     * the signal used by the group, and the second level is the group of
144
     * middlewares, sorted by descendant priority of each middleware.
145
     *
146
     * @return array
147
     */
148
    protected function getSignalSortedMiddlewares()
149
    {
150
        if (empty($this->signalSortedMiddlewares)) {
151
            $this->signalSortedMiddlewares = [];
152
            $middlewareList = [];
153
154
            foreach ($this->list as $middleware) {
155
                $signal = $middleware->getAttachedSignalName();
156
157
                if (false === isset($middlewareList[$signal])) {
158
                    $middlewareList[$signal] = [];
159
                }
160
161
                $middlewareList[$signal][] = $middleware;
162
            }
163
164
            foreach ($middlewareList as $key => $list) {
165
                $this->signalSortedMiddlewares[$key] = $this->sortMiddlewaresListByPriority($list);
166
            }
167
        }
168
169
        return $this->signalSortedMiddlewares;
170
    }
171
172
    /**
173
     * Will sort and return a middlewares list based on the priority of each
174
     * middleware. The middlewares with the highest priority will be placed at
175
     * the top of the list.
176
     *
177
     * @param array $list
178
     * @return array
179
     */
180
    private function sortMiddlewaresListByPriority(array $list)
181
    {
182
        usort($list, function (MiddlewareInterface $a, MiddlewareInterface $b) {
183
            $priorityA = (int)$a->getPriority();
184
            $priorityB = (int)$b->getPriority();
185
186
            if ($priorityA === $priorityB) {
187
                return 0;
188
            }
189
190
            return $priorityA < $priorityB
191
                ? 1
192
                : -1;
193
        });
194
195
        return $list;
196
    }
197
198
    /**
199
     * @return FormObject
200
     */
201
    public function getFormObject()
202
    {
203
        return $this->formObject;
204
    }
205
206
    /**
207
     * @return Request
208
     */
209
    public function getRequest()
210
    {
211
        return $this->request;
212
    }
213
214
    /**
215
     * @return Arguments
216
     */
217
    public function getRequestArguments()
218
    {
219
        return $this->requestArguments;
220
    }
221
}
222
223