Service::getDbRefResolvers()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
ccs 0
cts 4
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
/**
4
 * Minotaur
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
7
 * use this file except in compliance with the License. You may obtain a copy of
8
 * the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
 * License for the specific language governing permissions and limitations under
16
 * the License.
17
 *
18
 * @copyright 2015-2017 Appertly
19
 * @license   Apache-2.0
20
 */
21
namespace Minotaur\View;
22
23
use Caridea\Container\EmptyContainer;
24
25
/**
26
 * Creates Views and broadcasts the render event.
27
 */
28
class Service implements \Caridea\Container\ContainerAware
29
{
30
    use \Caridea\Container\ContainerSetter;
31
32
    /**
33
     * @var \Minotaur\View\Page The page, or null
34
     */
35
    private $page;
36
37
    /**
38
     * @var \Minotaur\View\BlockLayout The block layout, or null
39
     */
40
    private $blocks;
41
42
    /**
43
     * @var array<string> List of statuses
44
     */
45
    private const STATUSES = ['msg-warning', 'msg-info', 'msg-error'];
46
47
    /**
48
     * Creates a new ViewService.
49
     *
50
     * @param $container - The dependency injection container
51
     */
52
    public function __construct(?\Caridea\Container\Container $container)
53
    {
54
        $this->container = $container ?? new EmptyContainer();
55
    }
56
57
    /**
58
     * Gets the Page for this request (created lazily).
59
     *
60
     * @param string $title The page title
61
     * @return \Minotaur\View\Page A Page
62
     */
63
    public function getPage(string $title): Page
64
    {
65
        if ($this->page === null) {
66
            $page = (new Page())->setTitle($this->getPageTitle($title));
67
            $this->callPageVisitors($page);
68
            $this->page = $page;
69
        }
70
        return $this->page;
71
    }
72
73
    /**
74
     * Calls the page visitors.
75
     *
76
     * @param \Minotaur\View\Page $page The page to visit
77
     */
78
    protected function callPageVisitors(Page $page)
79
    {
80
        return array_map(function (PageVisitor $v) use ($page) {
81
            $v->visit($page);
82
        }, $this->container->getByType(PageVisitor::class));
83
    }
84
85
    /**
86
     * Generates a page title.
87
     *
88
     * @param string|null $title The page title
89
     * @return string The formatted page title
90
     */
91
    protected function getPageTitle(?string $title): string
92
    {
93
        return sprintf(
94
            $this->container->get('web.ui.title.template'),
95
            $title,
96
            $this->container->get('system.name')
97
        );
98
    }
99
100
    /**
101
     * Sets a Flash Message.
102
     *
103
     * @param string $name The status
104
     * @param string $value The message
105
     * @param bool $current Whether to add message to the current request
106
     */
107
    public function setFlashMessage(string $name, string $value, bool $current = false): void
108
    {
109
        $session = $this->container->getFirst(\Caridea\Session\Session::class);
110
        if ($session === null) {
111
            throw new \UnexpectedValueException("No Session Manager found");
112
        }
113
        $session->resume() || $session->start();
114
        $flash = $this->container->getFirst(\Caridea\Session\FlashPlugin::class);
115
        if ($flash === null) {
116
            throw new \UnexpectedValueException("No Flash Plugin found");
117
        }
118
        $flash->set($name, $value, $current);
119
    }
120
121
    /**
122
     * Clears Flash Messages.
123
     *
124
     * @param bool $current Whether to add message to the current request
125
     */
126
    public function clearFlashMessages(bool $current = false): void
127
    {
128
        $session = $this->container->getFirst(\Caridea\Session\Session::class);
129
        if ($session === null) {
130
            throw new \UnexpectedValueException("No Session Manager found");
131
        }
132
        $session->resume() || $session->start();
133
        $flash = $this->container->getFirst(\Caridea\Session\FlashPlugin::class);
134
        if ($flash === null) {
135
            throw new \UnexpectedValueException("No Flash Plugin found");
136
        }
137
        $flash->clear($current);
138
    }
139
140
    /**
141
     * Keeps all current flash messages for the next request.
142
     */
143
    public function keepFlashMessages(): void
144
    {
145
        $session = $this->container->getFirst(\Caridea\Session\Session::class);
146
        if ($session === null) {
147
            throw new \UnexpectedValueException("No Session Manager found");
148
        }
149
        $session->resume() || $session->start();
150
        $flash = $this->container->getFirst(\Caridea\Session\FlashPlugin::class);
151
        if ($flash === null) {
152
            throw new \UnexpectedValueException("No Flash Plugin found");
153
        }
154
        $flash->keep();
155
    }
156
157
    /**
158
     * Gets any flash messages in the session keyed by status.
159
     *
160
     * @return array<string,array<string>> map of flash messages
161
     */
162
    public function getFlashMessages(): array
163
    {
164
        $plugin = $this->container->getFirst(\Caridea\Session\FlashPlugin::class);
165
        if ($plugin === null) {
166
            throw new \UnexpectedValueException("No Flash Plugin found");
167
        }
168
        $map = [];
169
        foreach (self::STATUSES as $status) {
170
            $messages = $plugin->getCurrent($status);
171
            if (!$messages) {
172
                continue;
173
            }
174
            $vector = [];
175
            if (is_iterable($messages)) {
176
                foreach ($messages as $message) {
177
                    $vector[] = (string) $message;
178
                }
179
            } else {
180
                $vector[] = (string) $messages;
181
            }
182
            $map[$status] = $vector;
183
        }
184
        return $map;
185
    }
186
187
    /**
188
     * Gets the last request that the Dispatcher sent to a controller.
189
     *
190
     * @return \Psr\Http\Message\ServerRequestInterface The last dispatched request, or `null`
191
     */
192
    public function getDispatchedRequest(): ?\Psr\Http\Message\ServerRequestInterface
193
    {
194
        $c = $this->container ?? new EmptyContainer();
195
        $d = current($c->getByType(\Minotaur\Route\Dispatcher::class));
196
        return $d === null ? null : $d->getLastDispatchedRequest();
197
    }
198
199
    /**
200
     * Gets all blocks registered for a given region
201
     *
202
     * @param string $region The region to search
203
     * @return array<\Minotaur\View\Block> The found blocks in that region, or an empty array.
204
     */
205
    public function getBlocks(string $region): array
206
    {
207
        $c = $this->container ?? new EmptyContainer();
208
        $blocks = [];
209
        foreach ($this->getBlockLayout()->get($region) as $name) {
210
            $blocks[] = $c->named($name, Block::class);
211
        }
212
        return $blocks;
213
    }
214
215
    protected function getBlockLayout(): BlockLayout
216
    {
217
        if ($this->blocks === null) {
218
            $layout = new BlockLayout();
219
            $c = $this->container ?? new EmptyContainer();
220
            $layouts = $c->getByType(BlockLayout::class);
221
            if (count($layouts) === 0) {
222
                foreach ($c->getByType(Block::class) as $name => $block) {
223
                    if (method_exists($block, 'getRegion')) {
224
                        $region = $block->getRegion();
225
                        $order = !method_exists($block, 'getOrder') ? 0 :
226
                            (int) $block->getOrder();
227
                        $layout->add($region, $order, $name);
228
                    }
229
                }
230
            } else {
231
                foreach ($layouts as $bl) {
232
                    $layout->merge($bl);
233
                }
234
            }
235
            $this->blocks = $layout;
236
        }
237
        return $this->blocks;
238
    }
239
240
    /**
241
     * Gets any `Minotaur\Db\DbRefResolver` objects in the container.
242
     *
243
     * @return array<\Minotaur\Db\DbRefResolver> The DbRefResolver objects found.
244
     */
245
    public function getDbRefResolvers(): array
246
    {
247
        return $this->container->getByType(\Minotaur\Db\DbRefResolver::class);
248
    }
249
250
    /**
251
     * Gets any `Minotaur\View\EntityLinker` objects in the container.
252
     *
253
     * @return array<\Minotaur\View\EntityLinker> The EntityLinker objects found.
254
     */
255
    public function getEntityLinkers(): array
256
    {
257
        return $this->container->getByType(EntityLinker::class);
258
    }
259
260
    /**
261
     * Gets the CSRF token.
262
     *
263
     * @return string|null The CSRF token or `null`
264
     * @throws \UnexpectedValueException if the plugin wasn't in the container
265
     */
266
    public function getCsrfToken(): ?string
267
    {
268
        $plugin = $this->container->getFirst(\Caridea\Session\CsrfPlugin::class);
269
        if ($plugin === null) {
270
            throw new \UnexpectedValueException("No CSRF Plugin found");
271
        }
272
        return $plugin->getValue();
273
    }
274
275
    /**
276
     * Checks to see if the provided token matches the session CSRF token.
277
     *
278
     * @param string the provided token
279
     * @return bool whether the provided token matches
280
     * @throws \UnexpectedValueException if the plugin wasn't in the container
281
     */
282
    public function isCsrfValid(string $token): bool
283
    {
284
        $plugin = $this->container->getFirst(\Caridea\Session\CsrfPlugin::class);
285
        if ($plugin === null) {
286
            throw new \UnexpectedValueException("No CSRF Plugin found");
287
        }
288
        return $plugin->isValid($token);
289
    }
290
}
291