Issues (40)

php-src/Application/Routes/StrictRoute.php (1 issue)

Labels
Severity
1
<?php
2
3
namespace kalanis\Restful\Application\Routes;
4
5
6
use kalanis\Restful\Exceptions\InvalidArgumentException;
7
use Nette;
8
use Nette\Application;
9
use Nette\Http;
10
use Nette\Routing\Router;
11
use Nette\Utils\Strings;
12
use function str_contains;
13
14
15
/**
16
 * API strict route
17
 * - forces URL in form <prefix>/<presenter>[/<relation>[/<relationId>[/<relation>...]]]
18
 * - constructs app request to <Module>:<Presenter>:read<Relation[0]><Relation[1]>(<RelationId[0]>, <RelationId[1]>, ...)
19
 */
20
class StrictRoute implements Router
21
{
22
    private const
23
        PresenterKey = 'presenter',
24
        ModuleKey = 'module';
25
26
    /**
27
     * method dictionary
28
     * @var array<string, string>
29
     */
30
    protected array $methods = [
31
        Http\IRequest::Get => 'read',
32
        Http\IRequest::Post => 'create',
33
        Http\IRequest::Put => 'update',
34
        Http\IRequest::Delete => 'delete',
35
        Http\IRequest::Head => 'head',
36
        'PATCH' => 'patch',
37
        'OPTIONS' => 'options'
38
    ];
39
40
    public function __construct(
41
        protected string  $prefix = '',
42
        protected ?string $module = null,
43
    )
44
    {
45
    }
46
47
    /**
48
     * Match request
49
     * @param Http\IRequest $httpRequest
50
     * @return array<string, string>|null
51
     */
52
    public function match(Http\IRequest $httpRequest): ?array
53
    {
54
        $path = $httpRequest->getUrl()->getPathInfo();
55
        if (!str_contains($path, $this->prefix)) {
56
            return null;
57
        }
58
59
        $path = Strings::substring($path, strlen($this->prefix) + 1);
60
        $pathParts = explode('/', $path);
61
        $pathArguments = array_slice($pathParts, 1);
62
63
        $action = $this->getActionName($httpRequest->getMethod(), $pathArguments);
64
        $params = $this->getPathParameters($pathArguments);
65
        $params[self::ModuleKey] = $this->module;
66
        $params[self::PresenterKey] = $pathParts[0];
67
        $params['action'] = $action;
68
69
        $presenter = (is_string($this->module) ? $this->module . ':' : '') . $params[self::PresenterKey];
0 ignored issues
show
Are you sure $params[self::PresenterKey] of type array|string[] can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

69
        $presenter = (is_string($this->module) ? $this->module . ':' : '') . /** @scrutinizer ignore-type */ $params[self::PresenterKey];
Loading history...
70
71
        $appRequest = new Application\Request(
72
            $presenter,
73
            $httpRequest->getMethod(),
74
            $params,
75
            (array) $httpRequest->getPost(),
76
            $httpRequest->getFiles()
77
        );
78
        return $appRequest->toArray();
79
    }
80
81
    /**
82
     * Get action name
83
     * @param string $method
84
     * @param array<int, string> $arguments
85
     * @return string
86
     */
87
    private function getActionName(string $method, array $arguments): string
88
    {
89
        if (!isset($this->methods[$method])) {
90
            throw new InvalidArgumentException(
91
                'Request method must be one of ' . join(', ', array_keys($this->methods)) . ', ' . $method . ' given'
92
            );
93
        }
94
95
        $name = $this->methods[$method];
96
        for ($i = 0, $count = count($arguments); $i < $count; $i += 2) {
97
            $name .= Strings::firstUpper($arguments[$i]);
98
        }
99
        return $name;
100
    }
101
102
    /**
103
     * Get path parameters
104
     * @param array<int, string> $arguments
105
     * @return array<string, array<string>>
106
     */
107
    private function getPathParameters(array $arguments): array
108
    {
109
        $parameters = [];
110
        for ($i = 1, $count = count($arguments); $i < $count; $i += 2) {
111
            $parameters[] = $arguments[$i];
112
        }
113
        return ['params' => $parameters];
114
    }
115
116
    /**
117
     * @param array<string, mixed> $params
118
     * @param Http\UrlScript $refUrl
119
     * @return string|null
120
     */
121
    public function constructUrl(array $params, Nette\Http\UrlScript $refUrl): ?string
122
    {
123
        return null;
124
    }
125
}
126