misuzu/src/URLs/URLRegistry.php

100 lines
3.2 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.');
$this->infos[$name] = new URLInfo($name, $path, $query, $fragment);
}
public function registerInfo(URLInfo $info): void {
if(array_key_exists($info->getName(), $this->infos))
throw new InvalidArgumentException('A URL with $name has already been registered.');
$this->infos[$info->getName()] = $info;
}
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 = ($varName === 'page' ? $varValue < 2 : $varValue === 0) ? '' : (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;
}
}