@@ -54,6 +54,6 @@ |
||
54 | 54 | */ |
55 | 55 | private function generateMessage(): string |
56 | 56 | { |
57 | - return sprintf('The request target "%s" could not be matched!', $this->failedRequestTarget); |
|
57 | + return sprintf('The request target "%s" could not be matched!', $this->failedRequestTarget); |
|
58 | 58 | } |
59 | 59 | } |
@@ -17,109 +17,109 @@ |
||
17 | 17 | */ |
18 | 18 | final class UrlGenerator |
19 | 19 | { |
20 | - /** |
|
21 | - * @const string [RELATIVE_URI_REFERENCE_REGEX description] |
|
22 | - */ |
|
23 | - private const RELATIVE_URI_REFERENCE_REGEX = '~^//([^/?#]+)([^?#]*)(\?([^#]*))?~'; |
|
24 | - |
|
25 | - /** |
|
26 | - * @var Collection The route collection. |
|
27 | - */ |
|
28 | - private $routes; |
|
29 | - |
|
30 | - /** |
|
31 | - * @var string [$base description] |
|
32 | - */ |
|
33 | - private $base; |
|
34 | - |
|
35 | - /** |
|
36 | - * Constructs a new route path generator. |
|
37 | - * |
|
38 | - * @param Collection $routes The collection of "named" routes. |
|
39 | - */ |
|
40 | - public function __construct(Collection $routes) |
|
41 | - { |
|
42 | - $this->routes = $routes; |
|
43 | - $this->base = ''; |
|
44 | - } |
|
45 | - |
|
46 | - /** |
|
47 | - * Set a URL for the path to be appended to. |
|
48 | - * |
|
49 | - * @param string $relativeUri A relative URI reference (a URI without the scheme component). |
|
50 | - * @throws InvalidArgumentException If a relative URI reference was not provided. |
|
51 | - */ |
|
52 | - public function setBaseUrl(string $relativeUri): void |
|
53 | - { |
|
54 | - if (preg_match(self::RELATIVE_URI_REFERENCE_REGEX, $relativeUri) !== 1) { |
|
55 | - throw new InvalidArgumentException(sprintf('Invalid relative-uri reference "%s".', $relativeUri)); |
|
56 | - } |
|
57 | - |
|
58 | - $this->base = $relativeUri; |
|
59 | - } |
|
60 | - |
|
61 | - /** |
|
62 | - * Retrieve the URL that the path is being resolved against. |
|
63 | - * |
|
64 | - * @return string Either the URI that was set or an empty string if none was set. |
|
65 | - */ |
|
66 | - public function getBaseUrl(): string |
|
67 | - { |
|
68 | - return $this->base; |
|
69 | - } |
|
70 | - |
|
71 | - /** |
|
72 | - * Generates a URL for the given route name. |
|
73 | - * |
|
74 | - * @param string $name The route name. |
|
75 | - * @param mixed[] $parameters Replacements for named placeholders. |
|
76 | - * @throws RuntimeException If a route could not be found for the given name. |
|
77 | - * @return string The full protocol-less URL. |
|
78 | - */ |
|
79 | - public function generate(string $name, array $parameters = []) |
|
80 | - { |
|
81 | - foreach ($this->routes as $route) { |
|
82 | - if ($route->getName() === $name) { |
|
83 | - $requestTarget = $this->interpolate($route->getPattern(), $parameters); |
|
84 | - |
|
85 | - return $this->resolve($this->base, $requestTarget); |
|
86 | - } |
|
87 | - } |
|
88 | - |
|
89 | - throw new RuntimeException(sprintf('A route could not be found for "%s".', $name)); |
|
90 | - } |
|
91 | - |
|
92 | - /** |
|
93 | - * Resolve the request-target against a base URL. |
|
94 | - * |
|
95 | - * @param string $base A relative URI reference. |
|
96 | - * @param string $requestTarget The interpolated request-target. |
|
97 | - * @return string A protocol-relative (begins with two slashes) URL. |
|
98 | - */ |
|
99 | - protected function resolve(string $base, string $requestTarget): string |
|
100 | - { |
|
101 | - if ($base) { |
|
102 | - return rtrim($base . $requestTarget, '/'); |
|
103 | - } |
|
104 | - |
|
105 | - return $requestTarget; |
|
106 | - } |
|
107 | - |
|
108 | - /** |
|
109 | - * Replace placeholders in a template with their contextual values. |
|
110 | - * |
|
111 | - * @param Pattern $template The template/pattern to use. |
|
112 | - * @param mixed[] $parameters Replacements for the named placeholders. |
|
113 | - * @return string The pattern with the placeholders filled in. |
|
114 | - */ |
|
115 | - protected function interpolate(Pattern $template, array $parameters) |
|
116 | - { |
|
117 | - $replacements = []; |
|
118 | - |
|
119 | - foreach ($parameters as $key => $value) { |
|
120 | - $replacements[":{$key}"] = $value; |
|
121 | - } |
|
122 | - |
|
123 | - return strtr((string)$template, $replacements); |
|
124 | - } |
|
20 | + /** |
|
21 | + * @const string [RELATIVE_URI_REFERENCE_REGEX description] |
|
22 | + */ |
|
23 | + private const RELATIVE_URI_REFERENCE_REGEX = '~^//([^/?#]+)([^?#]*)(\?([^#]*))?~'; |
|
24 | + |
|
25 | + /** |
|
26 | + * @var Collection The route collection. |
|
27 | + */ |
|
28 | + private $routes; |
|
29 | + |
|
30 | + /** |
|
31 | + * @var string [$base description] |
|
32 | + */ |
|
33 | + private $base; |
|
34 | + |
|
35 | + /** |
|
36 | + * Constructs a new route path generator. |
|
37 | + * |
|
38 | + * @param Collection $routes The collection of "named" routes. |
|
39 | + */ |
|
40 | + public function __construct(Collection $routes) |
|
41 | + { |
|
42 | + $this->routes = $routes; |
|
43 | + $this->base = ''; |
|
44 | + } |
|
45 | + |
|
46 | + /** |
|
47 | + * Set a URL for the path to be appended to. |
|
48 | + * |
|
49 | + * @param string $relativeUri A relative URI reference (a URI without the scheme component). |
|
50 | + * @throws InvalidArgumentException If a relative URI reference was not provided. |
|
51 | + */ |
|
52 | + public function setBaseUrl(string $relativeUri): void |
|
53 | + { |
|
54 | + if (preg_match(self::RELATIVE_URI_REFERENCE_REGEX, $relativeUri) !== 1) { |
|
55 | + throw new InvalidArgumentException(sprintf('Invalid relative-uri reference "%s".', $relativeUri)); |
|
56 | + } |
|
57 | + |
|
58 | + $this->base = $relativeUri; |
|
59 | + } |
|
60 | + |
|
61 | + /** |
|
62 | + * Retrieve the URL that the path is being resolved against. |
|
63 | + * |
|
64 | + * @return string Either the URI that was set or an empty string if none was set. |
|
65 | + */ |
|
66 | + public function getBaseUrl(): string |
|
67 | + { |
|
68 | + return $this->base; |
|
69 | + } |
|
70 | + |
|
71 | + /** |
|
72 | + * Generates a URL for the given route name. |
|
73 | + * |
|
74 | + * @param string $name The route name. |
|
75 | + * @param mixed[] $parameters Replacements for named placeholders. |
|
76 | + * @throws RuntimeException If a route could not be found for the given name. |
|
77 | + * @return string The full protocol-less URL. |
|
78 | + */ |
|
79 | + public function generate(string $name, array $parameters = []) |
|
80 | + { |
|
81 | + foreach ($this->routes as $route) { |
|
82 | + if ($route->getName() === $name) { |
|
83 | + $requestTarget = $this->interpolate($route->getPattern(), $parameters); |
|
84 | + |
|
85 | + return $this->resolve($this->base, $requestTarget); |
|
86 | + } |
|
87 | + } |
|
88 | + |
|
89 | + throw new RuntimeException(sprintf('A route could not be found for "%s".', $name)); |
|
90 | + } |
|
91 | + |
|
92 | + /** |
|
93 | + * Resolve the request-target against a base URL. |
|
94 | + * |
|
95 | + * @param string $base A relative URI reference. |
|
96 | + * @param string $requestTarget The interpolated request-target. |
|
97 | + * @return string A protocol-relative (begins with two slashes) URL. |
|
98 | + */ |
|
99 | + protected function resolve(string $base, string $requestTarget): string |
|
100 | + { |
|
101 | + if ($base) { |
|
102 | + return rtrim($base . $requestTarget, '/'); |
|
103 | + } |
|
104 | + |
|
105 | + return $requestTarget; |
|
106 | + } |
|
107 | + |
|
108 | + /** |
|
109 | + * Replace placeholders in a template with their contextual values. |
|
110 | + * |
|
111 | + * @param Pattern $template The template/pattern to use. |
|
112 | + * @param mixed[] $parameters Replacements for the named placeholders. |
|
113 | + * @return string The pattern with the placeholders filled in. |
|
114 | + */ |
|
115 | + protected function interpolate(Pattern $template, array $parameters) |
|
116 | + { |
|
117 | + $replacements = []; |
|
118 | + |
|
119 | + foreach ($parameters as $key => $value) { |
|
120 | + $replacements[":{$key}"] = $value; |
|
121 | + } |
|
122 | + |
|
123 | + return strtr((string)$template, $replacements); |
|
124 | + } |
|
125 | 125 | } |
@@ -15,153 +15,153 @@ |
||
15 | 15 | */ |
16 | 16 | final class MatchResult |
17 | 17 | { |
18 | - /** |
|
19 | - * @const integer [FOUND description] |
|
20 | - */ |
|
21 | - const MATCHED = 200; |
|
22 | - |
|
23 | - /** |
|
24 | - * @const integer [NOT_FOUND description] |
|
25 | - */ |
|
26 | - const REQUEST_TARGET_NOT_MATCHED = 404; |
|
27 | - |
|
28 | - /** |
|
29 | - * @const integer [METHOD_NOT_ALLOWED description] |
|
30 | - */ |
|
31 | - const METHOD_NOT_MATCHED = 405; |
|
32 | - |
|
33 | - /** |
|
34 | - * @var integer [$type description] |
|
35 | - */ |
|
36 | - private $type; |
|
37 | - |
|
38 | - /** |
|
39 | - * @var ServerRequest [$request description] |
|
40 | - */ |
|
41 | - private $request; |
|
42 | - |
|
43 | - /** |
|
44 | - * @var Rule [$matchedRule description] |
|
45 | - */ |
|
46 | - private $matchedRule; |
|
47 | - |
|
48 | - /** |
|
49 | - * @var string[] [$allowedMethods description] |
|
50 | - */ |
|
51 | - private $allowedMethods; |
|
52 | - |
|
53 | - /** |
|
54 | - * [__construct description] |
|
55 | - * |
|
56 | - * @param integer $type [description] |
|
57 | - * @param ServerRequest $request [description] |
|
58 | - */ |
|
59 | - private function __construct(int $type, ServerRequest $request) |
|
60 | - { |
|
61 | - $this->type = $type; |
|
62 | - $this->request = $request; |
|
63 | - $this->allowedMethods = []; |
|
64 | - } |
|
65 | - |
|
66 | - /** |
|
67 | - * [getType description] |
|
68 | - * |
|
69 | - * @return integer [description] |
|
70 | - */ |
|
71 | - public function getType(): int |
|
72 | - { |
|
73 | - return $this->type; |
|
74 | - } |
|
75 | - |
|
76 | - /** |
|
77 | - * [getRequest description] |
|
78 | - * |
|
79 | - * @return ServerRequest [description] |
|
80 | - */ |
|
81 | - public function getRequest(): ServerRequest |
|
82 | - { |
|
83 | - return $this->request; |
|
84 | - } |
|
85 | - |
|
86 | - /** |
|
87 | - * [getMatchedRule description] |
|
88 | - * |
|
89 | - * @return Rule|null [description] |
|
90 | - */ |
|
91 | - public function getMatchedRule(): ?Rule |
|
92 | - { |
|
93 | - return $this->matchedRule; |
|
94 | - } |
|
95 | - |
|
96 | - /** |
|
97 | - * [getAllowedMethods description] |
|
98 | - * |
|
99 | - * @return string[] [description] |
|
100 | - */ |
|
101 | - public function getAllowedMethods(): array |
|
102 | - { |
|
103 | - return $this->allowedMethods; |
|
104 | - } |
|
105 | - |
|
106 | - /** |
|
107 | - * [isSuccessful description] |
|
108 | - * |
|
109 | - * @return boolean [description] |
|
110 | - */ |
|
111 | - public function isSuccessful(): bool |
|
112 | - { |
|
113 | - return $this->type === self::MATCHED; |
|
114 | - } |
|
115 | - |
|
116 | - /** |
|
117 | - * [isFailure description] |
|
118 | - * |
|
119 | - * @return boolean [description] |
|
120 | - */ |
|
121 | - public function isFailure(): bool |
|
122 | - { |
|
123 | - return $this->type === self::REQUEST_TARGET_NOT_MATCHED |
|
124 | - || $this->type === self::METHOD_NOT_MATCHED; |
|
125 | - } |
|
126 | - |
|
127 | - /** |
|
128 | - * [success description] |
|
129 | - * |
|
130 | - * @param ServerRequest $request [description] |
|
131 | - * @param Rule $rule [description] |
|
132 | - * @return self [description] |
|
133 | - */ |
|
134 | - public static function matched(ServerRequest $request, Rule $rule): self |
|
135 | - { |
|
136 | - $result = new self(self::MATCHED, $request); |
|
137 | - $result->matchedRule = $rule; |
|
138 | - |
|
139 | - return $result; |
|
140 | - } |
|
141 | - |
|
142 | - /** |
|
143 | - * [notFound description] |
|
144 | - * |
|
145 | - * @param ServerRequest $request [description] |
|
146 | - * @return self [description] |
|
147 | - */ |
|
148 | - public static function requestTargetNotMatched(ServerRequest $request): self |
|
149 | - { |
|
150 | - return new self(self::REQUEST_TARGET_NOT_MATCHED, $request); |
|
151 | - } |
|
152 | - |
|
153 | - /** |
|
154 | - * [methodNotAllowed description] |
|
155 | - * |
|
156 | - * @param ServerRequest $request [description] |
|
157 | - * @param string[] $allowedMethods [description] |
|
158 | - * @return self [description] |
|
159 | - */ |
|
160 | - public static function methodNotMatched(ServerRequest $request, array $allowedMethods): self |
|
161 | - { |
|
162 | - $result = new self(self::METHOD_NOT_MATCHED, $request); |
|
163 | - $result->allowedMethods = $allowedMethods; |
|
164 | - |
|
165 | - return $result; |
|
166 | - } |
|
18 | + /** |
|
19 | + * @const integer [FOUND description] |
|
20 | + */ |
|
21 | + const MATCHED = 200; |
|
22 | + |
|
23 | + /** |
|
24 | + * @const integer [NOT_FOUND description] |
|
25 | + */ |
|
26 | + const REQUEST_TARGET_NOT_MATCHED = 404; |
|
27 | + |
|
28 | + /** |
|
29 | + * @const integer [METHOD_NOT_ALLOWED description] |
|
30 | + */ |
|
31 | + const METHOD_NOT_MATCHED = 405; |
|
32 | + |
|
33 | + /** |
|
34 | + * @var integer [$type description] |
|
35 | + */ |
|
36 | + private $type; |
|
37 | + |
|
38 | + /** |
|
39 | + * @var ServerRequest [$request description] |
|
40 | + */ |
|
41 | + private $request; |
|
42 | + |
|
43 | + /** |
|
44 | + * @var Rule [$matchedRule description] |
|
45 | + */ |
|
46 | + private $matchedRule; |
|
47 | + |
|
48 | + /** |
|
49 | + * @var string[] [$allowedMethods description] |
|
50 | + */ |
|
51 | + private $allowedMethods; |
|
52 | + |
|
53 | + /** |
|
54 | + * [__construct description] |
|
55 | + * |
|
56 | + * @param integer $type [description] |
|
57 | + * @param ServerRequest $request [description] |
|
58 | + */ |
|
59 | + private function __construct(int $type, ServerRequest $request) |
|
60 | + { |
|
61 | + $this->type = $type; |
|
62 | + $this->request = $request; |
|
63 | + $this->allowedMethods = []; |
|
64 | + } |
|
65 | + |
|
66 | + /** |
|
67 | + * [getType description] |
|
68 | + * |
|
69 | + * @return integer [description] |
|
70 | + */ |
|
71 | + public function getType(): int |
|
72 | + { |
|
73 | + return $this->type; |
|
74 | + } |
|
75 | + |
|
76 | + /** |
|
77 | + * [getRequest description] |
|
78 | + * |
|
79 | + * @return ServerRequest [description] |
|
80 | + */ |
|
81 | + public function getRequest(): ServerRequest |
|
82 | + { |
|
83 | + return $this->request; |
|
84 | + } |
|
85 | + |
|
86 | + /** |
|
87 | + * [getMatchedRule description] |
|
88 | + * |
|
89 | + * @return Rule|null [description] |
|
90 | + */ |
|
91 | + public function getMatchedRule(): ?Rule |
|
92 | + { |
|
93 | + return $this->matchedRule; |
|
94 | + } |
|
95 | + |
|
96 | + /** |
|
97 | + * [getAllowedMethods description] |
|
98 | + * |
|
99 | + * @return string[] [description] |
|
100 | + */ |
|
101 | + public function getAllowedMethods(): array |
|
102 | + { |
|
103 | + return $this->allowedMethods; |
|
104 | + } |
|
105 | + |
|
106 | + /** |
|
107 | + * [isSuccessful description] |
|
108 | + * |
|
109 | + * @return boolean [description] |
|
110 | + */ |
|
111 | + public function isSuccessful(): bool |
|
112 | + { |
|
113 | + return $this->type === self::MATCHED; |
|
114 | + } |
|
115 | + |
|
116 | + /** |
|
117 | + * [isFailure description] |
|
118 | + * |
|
119 | + * @return boolean [description] |
|
120 | + */ |
|
121 | + public function isFailure(): bool |
|
122 | + { |
|
123 | + return $this->type === self::REQUEST_TARGET_NOT_MATCHED |
|
124 | + || $this->type === self::METHOD_NOT_MATCHED; |
|
125 | + } |
|
126 | + |
|
127 | + /** |
|
128 | + * [success description] |
|
129 | + * |
|
130 | + * @param ServerRequest $request [description] |
|
131 | + * @param Rule $rule [description] |
|
132 | + * @return self [description] |
|
133 | + */ |
|
134 | + public static function matched(ServerRequest $request, Rule $rule): self |
|
135 | + { |
|
136 | + $result = new self(self::MATCHED, $request); |
|
137 | + $result->matchedRule = $rule; |
|
138 | + |
|
139 | + return $result; |
|
140 | + } |
|
141 | + |
|
142 | + /** |
|
143 | + * [notFound description] |
|
144 | + * |
|
145 | + * @param ServerRequest $request [description] |
|
146 | + * @return self [description] |
|
147 | + */ |
|
148 | + public static function requestTargetNotMatched(ServerRequest $request): self |
|
149 | + { |
|
150 | + return new self(self::REQUEST_TARGET_NOT_MATCHED, $request); |
|
151 | + } |
|
152 | + |
|
153 | + /** |
|
154 | + * [methodNotAllowed description] |
|
155 | + * |
|
156 | + * @param ServerRequest $request [description] |
|
157 | + * @param string[] $allowedMethods [description] |
|
158 | + * @return self [description] |
|
159 | + */ |
|
160 | + public static function methodNotMatched(ServerRequest $request, array $allowedMethods): self |
|
161 | + { |
|
162 | + $result = new self(self::METHOD_NOT_MATCHED, $request); |
|
163 | + $result->allowedMethods = $allowedMethods; |
|
164 | + |
|
165 | + return $result; |
|
166 | + } |
|
167 | 167 | } |
@@ -16,24 +16,24 @@ discard block |
||
16 | 16 | */ |
17 | 17 | final class Rule |
18 | 18 | { |
19 | - /** |
|
20 | - * @var string [$method description] |
|
21 | - */ |
|
19 | + /** |
|
20 | + * @var string [$method description] |
|
21 | + */ |
|
22 | 22 | private $method; |
23 | 23 | |
24 | 24 | /** |
25 | - * @var Pattern [$pattern description] |
|
26 | - */ |
|
25 | + * @var Pattern [$pattern description] |
|
26 | + */ |
|
27 | 27 | private $pattern; |
28 | 28 | |
29 | 29 | /** |
30 | - * @var RequestHandler [$handler description] |
|
31 | - */ |
|
30 | + * @var RequestHandler [$handler description] |
|
31 | + */ |
|
32 | 32 | private $handler; |
33 | 33 | |
34 | 34 | /** |
35 | - * @var string [$name description] |
|
36 | - */ |
|
35 | + * @var string [$name description] |
|
36 | + */ |
|
37 | 37 | private $name; |
38 | 38 | |
39 | 39 | /** |
@@ -47,10 +47,10 @@ discard block |
||
47 | 47 | public function __construct(string $method, Pattern $pattern, RequestHandler $handler) |
48 | 48 | { |
49 | 49 | if (empty($method)) { |
50 | - throw new InvalidArgumentException('A request method was not provided.'); |
|
51 | - } |
|
50 | + throw new InvalidArgumentException('A request method was not provided.'); |
|
51 | + } |
|
52 | 52 | |
53 | - $this->method = $method; |
|
53 | + $this->method = $method; |
|
54 | 54 | $this->pattern = $pattern; |
55 | 55 | $this->handler = $handler; |
56 | 56 | $this->name = ''; |
@@ -106,12 +106,12 @@ discard block |
||
106 | 106 | */ |
107 | 107 | public function name(string $name): self |
108 | 108 | { |
109 | - if ($this->name) { |
|
110 | - throw new InvalidArgumentException('Name is immutable and cannot be changed once set.'); |
|
111 | - } |
|
109 | + if ($this->name) { |
|
110 | + throw new InvalidArgumentException('Name is immutable and cannot be changed once set.'); |
|
111 | + } |
|
112 | 112 | |
113 | 113 | if (empty($name)) { |
114 | - throw new InvalidArgumentException('Name cannot be empty.'); |
|
114 | + throw new InvalidArgumentException('Name cannot be empty.'); |
|
115 | 115 | } |
116 | 116 | |
117 | 117 | $this->name = $name; |
@@ -140,6 +140,6 @@ discard block |
||
140 | 140 | */ |
141 | 141 | public static function create(string $method, string $pattern, RequestHandler $handler): self |
142 | 142 | { |
143 | - return new self($method, new Pattern($pattern), $handler); |
|
143 | + return new self($method, new Pattern($pattern), $handler); |
|
144 | 144 | } |
145 | 145 | } |
@@ -12,7 +12,7 @@ discard block |
||
12 | 12 | */ |
13 | 13 | final class Pattern |
14 | 14 | { |
15 | - /** |
|
15 | + /** |
|
16 | 16 | * @const string [PLACEHOLDER_REGEX description] |
17 | 17 | */ |
18 | 18 | const PLACEHOLDER_SEARCH_REGEX = '~:([^/]+)~'; |
@@ -25,113 +25,113 @@ discard block |
||
25 | 25 | /** |
26 | 26 | * @var string [$pattern description] |
27 | 27 | */ |
28 | - private $pattern; |
|
29 | - |
|
30 | - /** |
|
31 | - * @var string[] [$placeholders description] |
|
32 | - */ |
|
33 | - private $placeholders; |
|
34 | - |
|
35 | - /** |
|
36 | - * Constructor. |
|
37 | - * |
|
38 | - * @param string $pattern [description] |
|
39 | - */ |
|
40 | - public function __construct(string $pattern) |
|
41 | - { |
|
42 | - $this->pattern = $this->stripQueryString($pattern); |
|
43 | - $this->placeholders = []; |
|
44 | - } |
|
45 | - |
|
46 | - /** |
|
47 | - * Retrieve any placeholders and their values. |
|
48 | - * |
|
49 | - * @return string[] The placeholder names and its values (only after compiling). |
|
50 | - */ |
|
51 | - public function getPlaceholders(): array |
|
52 | - { |
|
53 | - return $this->placeholders; |
|
54 | - } |
|
55 | - |
|
56 | - /** |
|
57 | - * Allow this object to be treated like a string. |
|
58 | - * |
|
59 | - * @return string The pattern BEFORE it's compiled. |
|
60 | - */ |
|
61 | - public function __toString(): string |
|
62 | - { |
|
63 | - return $this->pattern; |
|
64 | - } |
|
65 | - |
|
66 | - /** |
|
67 | - * Compile the request-target pattern into a regular expression. |
|
68 | - * |
|
69 | - * @todo Extract into a separate object along with the placeholders (something like `CompiledPattern`). |
|
70 | - * @return string A regular expression representing the pattern. |
|
71 | - */ |
|
72 | - public function compile(): string |
|
73 | - { |
|
74 | - $regex = preg_replace_callback(self::PLACEHOLDER_SEARCH_REGEX, [$this, 'extractPlaceholders'], $this->pattern); |
|
75 | - $regex = sprintf('~^%s$~', $regex); |
|
28 | + private $pattern; |
|
29 | + |
|
30 | + /** |
|
31 | + * @var string[] [$placeholders description] |
|
32 | + */ |
|
33 | + private $placeholders; |
|
34 | + |
|
35 | + /** |
|
36 | + * Constructor. |
|
37 | + * |
|
38 | + * @param string $pattern [description] |
|
39 | + */ |
|
40 | + public function __construct(string $pattern) |
|
41 | + { |
|
42 | + $this->pattern = $this->stripQueryString($pattern); |
|
43 | + $this->placeholders = []; |
|
44 | + } |
|
45 | + |
|
46 | + /** |
|
47 | + * Retrieve any placeholders and their values. |
|
48 | + * |
|
49 | + * @return string[] The placeholder names and its values (only after compiling). |
|
50 | + */ |
|
51 | + public function getPlaceholders(): array |
|
52 | + { |
|
53 | + return $this->placeholders; |
|
54 | + } |
|
55 | + |
|
56 | + /** |
|
57 | + * Allow this object to be treated like a string. |
|
58 | + * |
|
59 | + * @return string The pattern BEFORE it's compiled. |
|
60 | + */ |
|
61 | + public function __toString(): string |
|
62 | + { |
|
63 | + return $this->pattern; |
|
64 | + } |
|
65 | + |
|
66 | + /** |
|
67 | + * Compile the request-target pattern into a regular expression. |
|
68 | + * |
|
69 | + * @todo Extract into a separate object along with the placeholders (something like `CompiledPattern`). |
|
70 | + * @return string A regular expression representing the pattern. |
|
71 | + */ |
|
72 | + public function compile(): string |
|
73 | + { |
|
74 | + $regex = preg_replace_callback(self::PLACEHOLDER_SEARCH_REGEX, [$this, 'extractPlaceholders'], $this->pattern); |
|
75 | + $regex = sprintf('~^%s$~', $regex); |
|
76 | 76 | |
77 | 77 | return $regex; |
78 | - } |
|
79 | - |
|
80 | - /** |
|
81 | - * Compiles the pattern, checks if the request-target matches and extracts the placeholders. |
|
82 | - * |
|
83 | - * @param string $requestTarget The request-target to match against. |
|
84 | - * @return boolean `true` if compiled, matched and extracted successfully, `false` otherwise. |
|
85 | - */ |
|
86 | - public function matches(string $requestTarget): bool |
|
87 | - { |
|
88 | - $compiledPattern = $this->compile(); |
|
89 | - $requestTarget = $this->stripQueryString($requestTarget); |
|
90 | - |
|
91 | - if (preg_match($compiledPattern, $requestTarget, $matches) === 1) { |
|
92 | - $this->setPlaceholderValues($matches); |
|
93 | - |
|
94 | - return true; |
|
95 | - } |
|
96 | - |
|
97 | - return false; |
|
98 | - } |
|
99 | - |
|
100 | - /** |
|
101 | - * Extract placeholder names and give it an appropriate regex for matching. |
|
102 | - * |
|
103 | - * @param array $matches The matches returned from compile(). |
|
104 | - * @return string The regex to use in place of the placeholder name. |
|
105 | - */ |
|
106 | - private function extractPlaceholders(array $matches): string |
|
107 | - { |
|
108 | - $this->placeholders[$matches[1]] = null; |
|
109 | - |
|
110 | - return sprintf('(?<%s>[^/]+)', $matches[1]); |
|
111 | - } |
|
112 | - |
|
113 | - /** |
|
114 | - * Set the placeholder values from the match results. |
|
115 | - * |
|
116 | - * @param string[] $matches The results from preg_match(). |
|
117 | - */ |
|
118 | - private function setPlaceholderValues(array $matches): void |
|
119 | - { |
|
120 | - foreach ($this->placeholders as $key => $value) { |
|
121 | - if (isset($matches[$key])) { |
|
122 | - $this->placeholders[$key] = $matches[$key]; |
|
123 | - } |
|
124 | - } |
|
125 | - } |
|
126 | - |
|
127 | - /** |
|
128 | - * Remove the 'query string' part from a request-target. |
|
129 | - * |
|
130 | - * @param string $requestTarget The request-target which may or may not have a query string. |
|
131 | - * @return string The request-target without the query string. |
|
132 | - */ |
|
133 | - private function stripQueryString(string $requestTarget): string |
|
134 | - { |
|
135 | - return strpos($requestTarget, '?') !== false ? strstr($requestTarget, '?', true) : $requestTarget; |
|
136 | - } |
|
78 | + } |
|
79 | + |
|
80 | + /** |
|
81 | + * Compiles the pattern, checks if the request-target matches and extracts the placeholders. |
|
82 | + * |
|
83 | + * @param string $requestTarget The request-target to match against. |
|
84 | + * @return boolean `true` if compiled, matched and extracted successfully, `false` otherwise. |
|
85 | + */ |
|
86 | + public function matches(string $requestTarget): bool |
|
87 | + { |
|
88 | + $compiledPattern = $this->compile(); |
|
89 | + $requestTarget = $this->stripQueryString($requestTarget); |
|
90 | + |
|
91 | + if (preg_match($compiledPattern, $requestTarget, $matches) === 1) { |
|
92 | + $this->setPlaceholderValues($matches); |
|
93 | + |
|
94 | + return true; |
|
95 | + } |
|
96 | + |
|
97 | + return false; |
|
98 | + } |
|
99 | + |
|
100 | + /** |
|
101 | + * Extract placeholder names and give it an appropriate regex for matching. |
|
102 | + * |
|
103 | + * @param array $matches The matches returned from compile(). |
|
104 | + * @return string The regex to use in place of the placeholder name. |
|
105 | + */ |
|
106 | + private function extractPlaceholders(array $matches): string |
|
107 | + { |
|
108 | + $this->placeholders[$matches[1]] = null; |
|
109 | + |
|
110 | + return sprintf('(?<%s>[^/]+)', $matches[1]); |
|
111 | + } |
|
112 | + |
|
113 | + /** |
|
114 | + * Set the placeholder values from the match results. |
|
115 | + * |
|
116 | + * @param string[] $matches The results from preg_match(). |
|
117 | + */ |
|
118 | + private function setPlaceholderValues(array $matches): void |
|
119 | + { |
|
120 | + foreach ($this->placeholders as $key => $value) { |
|
121 | + if (isset($matches[$key])) { |
|
122 | + $this->placeholders[$key] = $matches[$key]; |
|
123 | + } |
|
124 | + } |
|
125 | + } |
|
126 | + |
|
127 | + /** |
|
128 | + * Remove the 'query string' part from a request-target. |
|
129 | + * |
|
130 | + * @param string $requestTarget The request-target which may or may not have a query string. |
|
131 | + * @return string The request-target without the query string. |
|
132 | + */ |
|
133 | + private function stripQueryString(string $requestTarget): string |
|
134 | + { |
|
135 | + return strpos($requestTarget, '?') !== false ? strstr($requestTarget, '?', true) : $requestTarget; |
|
136 | + } |
|
137 | 137 | } |
@@ -18,7 +18,7 @@ discard block |
||
18 | 18 | */ |
19 | 19 | class Collection implements IteratorAggregate, Countable |
20 | 20 | { |
21 | - /** |
|
21 | + /** |
|
22 | 22 | * @var Rule[] [$rules description] |
23 | 23 | */ |
24 | 24 | private $rules = []; |
@@ -49,7 +49,7 @@ discard block |
||
49 | 49 | $index = $this->indexOf($rule); |
50 | 50 | |
51 | 51 | if ($index === -1) { |
52 | - throw new LogicException('Cannot remove a rule that is not in the collection.'); |
|
52 | + throw new LogicException('Cannot remove a rule that is not in the collection.'); |
|
53 | 53 | } |
54 | 54 | |
55 | 55 | unset($this->rules[$index]); |
@@ -102,7 +102,7 @@ discard block |
||
102 | 102 | */ |
103 | 103 | public function isEmpty(): bool |
104 | 104 | { |
105 | - return empty($this->rules); |
|
105 | + return empty($this->rules); |
|
106 | 106 | } |
107 | 107 | |
108 | 108 | /** |
@@ -57,7 +57,7 @@ |
||
57 | 57 | $allowedMethods[] = $matchedRule->getMethod(); |
58 | 58 | |
59 | 59 | if ($matchedRule->matchesMethod($request->getMethod())) { |
60 | - return MatchResult::matched($request, $matchedRule); |
|
60 | + return MatchResult::matched($request, $matchedRule); |
|
61 | 61 | } |
62 | 62 | } |
63 | 63 |