99 lines
2.2 KiB
PHP
99 lines
2.2 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace Rize;
|
||
|
|
|
||
|
|
use Rize\UriTemplate\Parser;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* URI Template.
|
||
|
|
*/
|
||
|
|
class UriTemplate
|
||
|
|
{
|
||
|
|
protected Parser $parser;
|
||
|
|
protected array $parsed = [];
|
||
|
|
|
||
|
|
public function __construct(protected string $base_uri = '', protected array $params = [], ?Parser $parser = null)
|
||
|
|
{
|
||
|
|
$this->parser = $parser ?: $this->createNodeParser();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Expands URI Template.
|
||
|
|
*
|
||
|
|
* @param mixed $params
|
||
|
|
*/
|
||
|
|
public function expand(string $uri, $params = []): string
|
||
|
|
{
|
||
|
|
$params += $this->params;
|
||
|
|
$uri = $this->base_uri . $uri;
|
||
|
|
$result = [];
|
||
|
|
|
||
|
|
// quick check
|
||
|
|
if (!str_contains($uri, '{')) {
|
||
|
|
return $uri;
|
||
|
|
}
|
||
|
|
|
||
|
|
$parser = $this->parser;
|
||
|
|
$nodes = $parser->parse($uri);
|
||
|
|
|
||
|
|
foreach ($nodes as $node) {
|
||
|
|
$result[] = $node->expand($parser, $params);
|
||
|
|
}
|
||
|
|
|
||
|
|
return implode('', $result);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Extracts variables from URI.
|
||
|
|
*
|
||
|
|
* @return null|array params or null if not match and $strict is true
|
||
|
|
*/
|
||
|
|
public function extract(string $template, string $uri, bool $strict = false): ?array
|
||
|
|
{
|
||
|
|
$params = [];
|
||
|
|
$nodes = $this->parser->parse($template);
|
||
|
|
|
||
|
|
// PHP 8.1.0RC4-dev still throws deprecation warning for `strlen`.
|
||
|
|
// $uri = (string) $uri;
|
||
|
|
|
||
|
|
foreach ($nodes as $node) {
|
||
|
|
// if strict is given, and there's no remaining uri just return null
|
||
|
|
if ($strict && (string) $uri === '') {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
// URI will be truncated from the start when a match is found
|
||
|
|
$match = $node->match($this->parser, $uri, $params, $strict);
|
||
|
|
|
||
|
|
if ($match === null) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
[$uri, $params] = $match;
|
||
|
|
}
|
||
|
|
|
||
|
|
// if there's remaining $uri, matching is failed
|
||
|
|
if ($strict && (string) $uri !== '') {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
return $params;
|
||
|
|
}
|
||
|
|
|
||
|
|
public function getParser(): Parser
|
||
|
|
{
|
||
|
|
return $this->parser;
|
||
|
|
}
|
||
|
|
|
||
|
|
protected function createNodeParser(): Parser
|
||
|
|
{
|
||
|
|
static $parser;
|
||
|
|
|
||
|
|
if ($parser) {
|
||
|
|
return $parser;
|
||
|
|
}
|
||
|
|
|
||
|
|
return $parser = new Parser();
|
||
|
|
}
|
||
|
|
}
|