Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
93.75% covered (success)
93.75%
30 / 32
66.67% covered (warning)
66.67%
4 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
MiddlewareRequestHandler
93.75% covered (success)
93.75%
30 / 32
66.67% covered (warning)
66.67%
4 / 6
11.03
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 handle
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 withOriginalResponse
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 createMiddlewareQueue
91.67% covered (success)
91.67%
11 / 12
0.00% covered (danger)
0.00%
0 / 1
2.00
 discoverMiddlewareIds
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
4
 getMiddleware
75.00% covered (warning)
75.00%
3 / 4
0.00% covered (danger)
0.00%
0 / 1
2.06
1<?php
2
3/*
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; under version 2
7 * of the License (non-upgradable).
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 *
18 * Copyright (c) 2021-2022 (original work) Open Assessment Technologies SA
19 *
20 * @author Gabriel Felipe Soares <gabriel.felipe.soares@taotesting.com>
21 */
22
23declare(strict_types=1);
24
25namespace oat\generis\model\Middleware;
26
27use LogicException;
28use Psr\Container\ContainerInterface;
29use Psr\Http\Message\RequestInterface;
30use Psr\Http\Message\ResponseInterface;
31use Psr\Http\Message\ServerRequestInterface;
32use Psr\Http\Server\MiddlewareInterface;
33use Psr\Http\Server\RequestHandlerInterface;
34use Relay\RelayBuilder;
35
36class MiddlewareRequestHandler implements RequestHandlerInterface
37{
38    /** @var ResponseInterface|null */
39    private $originalResponse;
40
41    /** @var array[] */
42    private $middlewareMap;
43
44    /** @var ContainerInterface */
45    private $container;
46
47    /** @var RelayBuilder */
48    private $relayBuilder;
49
50    public function __construct(ContainerInterface $container, RelayBuilder $relayBuilder, array $middlewareMap)
51    {
52        $this->container = $container;
53        $this->middlewareMap = $middlewareMap;
54        $this->relayBuilder = $relayBuilder;
55    }
56
57    public function handle(ServerRequestInterface $request): ResponseInterface
58    {
59        return $this->relayBuilder
60            ->newInstance($this->createMiddlewareQueue($request))
61            ->handle($request);
62    }
63
64    public function withOriginalResponse(ResponseInterface $response): self
65    {
66        $this->originalResponse = $response;
67
68        return $this;
69    }
70
71    /**
72     * @return MiddlewareInterface[]
73     */
74    private function createMiddlewareQueue(RequestInterface $request): array
75    {
76        $mapping = [];
77
78        foreach ($this->discoverMiddlewareIds($request) as $middlewareId) {
79            $mapping[] = $this->getMiddleware($middlewareId);
80        }
81
82        $originalResponse = $this->originalResponse;
83
84        return array_merge(
85            $mapping,
86            [
87                static function ($request, $next) use ($originalResponse): ResponseInterface {
88                    return $originalResponse;
89                }
90            ]
91        );
92    }
93
94    /**
95     * @return string[]
96     */
97    private function discoverMiddlewareIds(RequestInterface $request): array
98    {
99        $filteredMap = [];
100        $preparedRoute = $request->getMethod() . $request->getUri()->getPath();
101
102        foreach ($this->middlewareMap as $routeRegex => $mapGroup) {
103            if (preg_match($routeRegex, $preparedRoute) !== 1) {
104                continue;
105            }
106
107            foreach ($mapGroup as $map) {
108                $filteredMap = array_merge($filteredMap, MiddlewareMap::fromJson($map)->getMiddlewaresIds());
109            }
110        }
111
112        return $filteredMap;
113    }
114
115    private function getMiddleware(string $middlewareId): MiddlewareInterface
116    {
117        $middleware = $this->container->get($middlewareId);
118
119        if ($middleware instanceof MiddlewareInterface) {
120            return $middleware;
121        }
122
123        throw new LogicException(sprintf('Incorrect middleware configuration for %s', $middlewareId));
124    }
125}