chore: update console components, logging, router and add subdomain support

This commit is contained in:
2025-11-03 12:44:39 +01:00
parent 6d355c9897
commit ee06cbbbf1
18 changed files with 2080 additions and 113 deletions

View File

@@ -0,0 +1,82 @@
<?php
declare(strict_types=1);
namespace App\Framework\Http\Url;
use Stringable;
final class Subdomain implements Stringable
{
public function __construct(
public string $value
){}
public static function fromHost(string $host, string $base): Subdomain
{
if(!str_ends_with($host, '.'.$base)) {
throw new \InvalidArgumentException('Host does not end with base domain');
}
$subdomain = self::str_trim_end($host, '.'.$base);
return new Subdomain($subdomain);
}
public static function tryFromHost(string $host, string $base): ?Subdomain
{
try {
return self::fromHost($host, $base);
} catch (\InvalidArgumentException $e) {
return null;
}
}
public function __toString(): string
{
return $this->value;
}
private function validate(string $subdomain):bool
{
return is_string($subdomain);
}
private static function str_trim_end(string $string, string $end, bool $utf8 = false): string
{
if($end === '') {
return $string;
}
if ($utf8) {
if (!self::mb_str_ends_with($string, $end)) {
return $string;
}
return mb_substr($string, 0, -mb_strlen($end));
}
if(!str_ends_with($string, $end)) {
return $string;
}
return substr($string, 0, -strlen($end));
}
private static function mb_str_ends_with(string $haystack, string $needle, string $encoding = 'UTF-8'): bool
{
$len = mb_strlen($needle, $encoding);
if ($len === 0) {
return true;
}
return (mb_substr($haystack, -$len, null, $encoding) === $needle);
}
private static function mb_str_starts_with(string $haystack, string $needle, string $encoding = 'UTF-8'): bool
{
$len = mb_strlen($needle, $encoding);
if ($len === 0) {
return true;
}
return (mb_substr($haystack, 0, $len, $encoding) === $needle);
}
}