FastRouterHandler   A
last analyzed

Complexity

Total Complexity 7

Size/Duplication

Total Lines 82
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 7
eloc 51
c 1
b 0
f 0
dl 0
loc 82
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 1
A createDispatcherCallable() 0 15 1
A dispatch() 0 41 5
1
<?php
2
/**
3
 * This file is part of Phiremock.
4
 *
5
 * Phiremock is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU Lesser General Public License as published by
7
 * the Free Software Foundation, either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * Phiremock is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with Phiremock.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18
19
namespace Mcustiel\Phiremock\Server\Http\Implementation;
20
21
use FastRoute\Dispatcher;
22
use FastRoute\RouteCollector;
23
use function FastRoute\simpleDispatcher;
24
use Laminas\Diactoros\Response;
25
use Mcustiel\Phiremock\Common\StringStream;
26
use Mcustiel\Phiremock\Server\Actions\ActionLocator;
27
use Mcustiel\Phiremock\Server\Http\RequestHandlerInterface;
28
use Mcustiel\Phiremock\Server\Utils\Config\Config;
29
use Psr\Http\Message\ResponseInterface;
30
use Psr\Http\Message\ServerRequestInterface;
31
use Psr\Log\LoggerInterface;
32
use Throwable;
33
34
class FastRouterHandler implements RequestHandlerInterface
35
{
36
    /** @var Dispatcher */
37
    private $dispatcher;
38
    /** @var ActionLocator */
39
    private $actionsLocator;
40
    /** @var LoggerInterface */
41
    private $logger;
42
43
    public function __construct(ActionLocator $locator, Config $config, LoggerInterface $logger)
44
    {
45
        $this->dispatcher = simpleDispatcher(
46
            $this->createDispatcherCallable(),
47
            [
48
                'cacheFile'     => __DIR__ . '/route.cache',
49
                'cacheDisabled' => $config->isDebugMode(),
50
            ]
51
        );
52
        $this->actionsLocator = $locator;
53
        $this->logger = $logger;
54
    }
55
56
    public function dispatch(ServerRequestInterface $request): ResponseInterface
57
    {
58
        $uri = $request->getUri()->getPath();
59
        $routeInfo = $this->dispatcher->dispatch($request->getMethod(), $uri);
60
        try {
61
            switch ($routeInfo[0]) {
62
                case Dispatcher::NOT_FOUND:
63
                    return $this->actionsLocator
64
                        ->locate(ActionLocator::MANAGE_REQUEST)
65
                        ->execute($request, new Response());
66
                case Dispatcher::METHOD_NOT_ALLOWED:
67
                    return new Response(
68
                        sprintf(
69
                            'Method not allowed. Allowed methods for %s: %s',
70
                            $uri,
71
                            implode(', ', $routeInfo[1])
72
                        ),
73
                        405
74
                    );
75
                case Dispatcher::FOUND:
76
                    return $this->actionsLocator
77
                        ->locate($routeInfo[1])
78
                        ->execute($request, new Response());
79
            }
80
81
            return new Response(
82
                new StringStream(
83
                    json_encode(['result' => 'ERROR', 'details' => 'Unexpected error: Router returned unexpected info'])
84
                ),
85
                500,
86
                ['Content-Type' => 'application/json']
87
            );
88
        } catch (Throwable $e) {
89
            $this->logger->error($e->getMessage());
90
91
            return new Response(
92
                new StringStream(
93
                    json_encode(['result' => 'ERROR', 'details' => $e->getMessage()])
94
                ),
95
                500,
96
                ['Content-Type' => 'application/json']
97
            );
98
        }
99
    }
100
101
    private function createDispatcherCallable(): callable
102
    {
103
        return function (RouteCollector $r) {
104
            $r->addRoute('GET', '/__phiremock/expectations', ActionLocator::LIST_EXPECTATIONS);
105
            $r->addRoute('POST', '/__phiremock/expectations', ActionLocator::ADD_EXPECTATION);
106
            $r->addRoute('DELETE', '/__phiremock/expectations', ActionLocator::CLEAR_EXPECTATIONS);
107
108
            $r->addRoute('PUT', '/__phiremock/scenarios', ActionLocator::SET_SCENARIO_STATE);
109
            $r->addRoute('DELETE', '/__phiremock/scenarios', ActionLocator::CLEAR_SCENARIOS);
110
111
            $r->addRoute('POST', '/__phiremock/executions', ActionLocator::COUNT_REQUESTS);
112
            $r->addRoute('PUT', '/__phiremock/executions', ActionLocator::LIST_REQUESTS);
113
            $r->addRoute('DELETE', '/__phiremock/executions', ActionLocator::RESET_REQUESTS_COUNT);
114
115
            $r->addRoute('POST', '/__phiremock/reset', ActionLocator::RESET);
116
        };
117
    }
118
}
119