97 lines
3.1 KiB
PHP
97 lines
3.1 KiB
PHP
<?php
|
|
namespace Misuzu\URLs;
|
|
|
|
use InvalidArgumentException;
|
|
|
|
class URLRegistry {
|
|
private array $infos = [];
|
|
|
|
public function register(string $name, string $path, array $query = [], string $fragment = ''): void {
|
|
if(array_key_exists($name, $this->infos))
|
|
throw new InvalidArgumentException('A URL with $name has already been registered.');
|
|
if($path === '')
|
|
throw new InvalidArgumentException('$path may not be empty.');
|
|
if($path[0] !== '/')
|
|
throw new InvalidArgumentException('$path must begin with /.');
|
|
|
|
$this->infos[$name] = new URLInfo($name, $path, $query, $fragment);
|
|
}
|
|
|
|
public function format(string $name, array $vars = [], bool $spacesAsPlus = false): string {
|
|
if(!array_key_exists($name, $this->infos))
|
|
return '';
|
|
|
|
$urlInfo = $this->infos[$name];
|
|
$urlStr = self::replaceVariables($urlInfo->getPath(), $vars);
|
|
|
|
if($urlInfo->hasQuery()) {
|
|
$query = [];
|
|
$queryParts = $urlInfo->getQuery();
|
|
foreach($queryParts as $name => $value) {
|
|
$value = self::replaceVariables($value, $vars);
|
|
if($value !== '' && !($name === 'page' && (int)$value <= 1))
|
|
$query[$name] = $value;
|
|
}
|
|
|
|
if(!empty($query))
|
|
$urlStr .= '?' . http_build_query($query, '', '&', $spacesAsPlus ? PHP_QUERY_RFC1738 : PHP_QUERY_RFC3986);
|
|
}
|
|
|
|
if($urlInfo->hasFragment()) {
|
|
$fragment = self::replaceVariables($urlInfo->getFragment(), $vars);
|
|
if($fragment !== '')
|
|
$urlStr .= '#' . $fragment;
|
|
}
|
|
|
|
return $urlStr;
|
|
}
|
|
|
|
public static function replaceVariables(string $str, array $vars): string {
|
|
// i: have no idea what i'm doing
|
|
$out = '';
|
|
$varName = '';
|
|
$inVarName = false;
|
|
|
|
$length = strlen($str);
|
|
for($i = 0; $i < $length; ++$i) {
|
|
$char = $str[$i];
|
|
|
|
if($inVarName) {
|
|
if($char === '>') {
|
|
$inVarName = false;
|
|
if(array_key_exists($varName, $vars)) {
|
|
$varValue = $vars[$varName];
|
|
if(is_array($varValue))
|
|
$varValue = empty($varValue) ? '' : implode(',', $varValue);
|
|
elseif(is_int($varValue))
|
|
$varValue = $varValue < ($varName === 'page' ? 2 : 1) ? '' : (string)$varValue;
|
|
else
|
|
$varValue = (string)$varValue;
|
|
} else
|
|
$varValue = '';
|
|
|
|
$out .= $varValue;
|
|
$varName = '';
|
|
continue;
|
|
}
|
|
|
|
if($char === '<') {
|
|
$out .= '<' . $varName;
|
|
$varName = '';
|
|
continue;
|
|
}
|
|
|
|
$varName .= $char;
|
|
} else
|
|
$inVarName = $char === '<';
|
|
|
|
if(!$inVarName)
|
|
$out .= $char;
|
|
}
|
|
|
|
if($varName !== '')
|
|
$out .= $varName;
|
|
|
|
return $out;
|
|
}
|
|
}
|