chore: fix PSR-12 coding style violations using PHPCBF
Some checks are pending
CI / build (push) Waiting to run

This commit is contained in:
Funky Waddle 2026-02-15 13:15:55 -06:00
parent 41c8c9457c
commit 83c18bd82d
12 changed files with 338 additions and 116 deletions

View file

@ -21,7 +21,7 @@ class ListRoutesCommand
$json = in_array('--json', $argv);
$routes = $router->getRoutes();
$output = [];
foreach ($routes as $route) {
$output[] = $route->toArray();
}
@ -32,10 +32,11 @@ class ListRoutesCommand
printf("%-10s | %-30s | %-20s | %-30s\n", "Method", "Path", "Name", "Handler");
echo str_repeat("-", 100) . PHP_EOL;
foreach ($output as $r) {
printf("%-10s | %-30s | %-20s | %-30s\n",
$r['method'],
$r['path'],
$r['name'] ?? '',
printf(
"%-10s | %-30s | %-20s | %-30s\n",
$r['method'],
$r['path'],
$r['name'] ?? '',
is_string($r['handler']) ? $r['handler'] : 'Closure'
);
}

View file

@ -25,76 +25,261 @@ class TestRouteCommand
$host = 'localhost'; // Default
// PSR-7 mock request
$uri = new class($path, $host) implements UriInterface {
public function __construct(private $path, private $host) {}
public function getScheme(): string { return 'http'; }
public function getAuthority(): string { return $this->host; }
public function getUserInfo(): string { return ''; }
public function getHost(): string { return $this->host; }
public function getPort(): ?int { return null; }
public function getPath(): string { return $this->path; }
public function getQuery(): string { return ''; }
public function getFragment(): string { return ''; }
public function withScheme($scheme): UriInterface { return $this; }
public function withUserInfo($user, $password = null): UriInterface { return $this; }
public function withHost($host): UriInterface { return $this; }
public function withPort($port): UriInterface { return $this; }
public function withPath($path): UriInterface { return $this; }
public function withQuery($query): UriInterface { return $this; }
public function withFragment($fragment): UriInterface { return $this; }
public function __toString(): string { return "http://{$this->host}{$this->path}"; }
$uri = new class ($path, $host) implements UriInterface {
public function __construct(private $path, private $host)
{
}
public function getScheme(): string
{
return 'http';
}
public function getAuthority(): string
{
return $this->host;
}
public function getUserInfo(): string
{
return '';
}
public function getHost(): string
{
return $this->host;
}
public function getPort(): ?int
{
return null;
}
public function getPath(): string
{
return $this->path;
}
public function getQuery(): string
{
return '';
}
public function getFragment(): string
{
return '';
}
public function withScheme($scheme): UriInterface
{
return $this;
}
public function withUserInfo($user, $password = null): UriInterface
{
return $this;
}
public function withHost($host): UriInterface
{
return $this;
}
public function withPort($port): UriInterface
{
return $this;
}
public function withPath($path): UriInterface
{
return $this;
}
public function withQuery($query): UriInterface
{
return $this;
}
public function withFragment($fragment): UriInterface
{
return $this;
}
public function __toString(): string
{
return "http://{$this->host}{$this->path}";
}
};
$request = new class($method, $uri) implements ServerRequestInterface {
public function __construct(private $method, private $uri) {}
public function getProtocolVersion(): string { return '1.1'; }
public function withProtocolVersion($version): ServerRequestInterface { return $this; }
public function getHeaders(): array { return []; }
public function hasHeader($name): bool { return false; }
public function getHeader($name): array { return []; }
public function getHeaderLine($name): string { return ''; }
public function withHeader($name, $value): ServerRequestInterface { return $this; }
public function withAddedHeader($name, $value): ServerRequestInterface { return $this; }
public function withoutHeader($name): ServerRequestInterface { return $this; }
public function getBody(): \Psr\Http\Message\StreamInterface { return $this->createMockStream(); }
public function withBody(\Psr\Http\Message\StreamInterface $body): ServerRequestInterface { return $this; }
public function getRequestTarget(): string { return $this->uri->getPath(); }
public function withRequestTarget($requestTarget): ServerRequestInterface { return $this; }
public function getMethod(): string { return $this->method; }
public function withMethod($method): ServerRequestInterface { return $this; }
public function getUri(): UriInterface { return $this->uri; }
public function withUri(UriInterface $uri, $preserveHost = false): ServerRequestInterface { return $this; }
public function getServerParams(): array { return []; }
public function getCookieParams(): array { return []; }
public function withCookieParams(array $cookies): ServerRequestInterface { return $this; }
public function getQueryParams(): array { return []; }
public function withQueryParams(array $query): ServerRequestInterface { return $this; }
public function getUploadedFiles(): array { return []; }
public function withUploadedFiles(array $uploadedFiles): ServerRequestInterface { return $this; }
public function getParsedBody(): null|array|object { return null; }
public function withParsedBody($data): ServerRequestInterface { return $this; }
public function getAttributes(): array { return []; }
public function getAttribute($name, $default = null): mixed { return $default; }
public function withAttribute($name, $value): ServerRequestInterface { return $this; }
public function withoutAttribute($name): ServerRequestInterface { return $this; }
$request = new class ($method, $uri) implements ServerRequestInterface {
public function __construct(private $method, private $uri)
{
}
public function getProtocolVersion(): string
{
return '1.1';
}
public function withProtocolVersion($version): ServerRequestInterface
{
return $this;
}
public function getHeaders(): array
{
return [];
}
public function hasHeader($name): bool
{
return false;
}
public function getHeader($name): array
{
return [];
}
public function getHeaderLine($name): string
{
return '';
}
public function withHeader($name, $value): ServerRequestInterface
{
return $this;
}
public function withAddedHeader($name, $value): ServerRequestInterface
{
return $this;
}
public function withoutHeader($name): ServerRequestInterface
{
return $this;
}
public function getBody(): \Psr\Http\Message\StreamInterface
{
return $this->createMockStream();
}
public function withBody(\Psr\Http\Message\StreamInterface $body): ServerRequestInterface
{
return $this;
}
public function getRequestTarget(): string
{
return $this->uri->getPath();
}
public function withRequestTarget($requestTarget): ServerRequestInterface
{
return $this;
}
public function getMethod(): string
{
return $this->method;
}
public function withMethod($method): ServerRequestInterface
{
return $this;
}
public function getUri(): UriInterface
{
return $this->uri;
}
public function withUri(UriInterface $uri, $preserveHost = false): ServerRequestInterface
{
return $this;
}
public function getServerParams(): array
{
return [];
}
public function getCookieParams(): array
{
return [];
}
public function withCookieParams(array $cookies): ServerRequestInterface
{
return $this;
}
public function getQueryParams(): array
{
return [];
}
public function withQueryParams(array $query): ServerRequestInterface
{
return $this;
}
public function getUploadedFiles(): array
{
return [];
}
public function withUploadedFiles(array $uploadedFiles): ServerRequestInterface
{
return $this;
}
public function getParsedBody(): null|array|object
{
return null;
}
public function withParsedBody($data): ServerRequestInterface
{
return $this;
}
public function getAttributes(): array
{
return [];
}
public function getAttribute($name, $default = null): mixed
{
return $default;
}
public function withAttribute($name, $value): ServerRequestInterface
{
return $this;
}
public function withoutAttribute($name): ServerRequestInterface
{
return $this;
}
private function createMockStream() {
private function createMockStream()
{
return new class implements \Psr\Http\Message\StreamInterface {
public function __toString(): string { return ''; }
public function close(): void {}
public function detach() { return null; }
public function getSize(): ?int { return 0; }
public function tell(): int { return 0; }
public function eof(): bool { return true; }
public function isSeekable(): bool { return false; }
public function seek($offset, $whence = SEEK_SET): void {}
public function rewind(): void {}
public function isWritable(): bool { return false; }
public function write($string): int { return 0; }
public function isReadable(): bool { return true; }
public function read($length): string { return ''; }
public function getContents(): string { return ''; }
public function getMetadata($key = null) { return $key ? null : []; }
public function __toString(): string
{
return '';
}
public function close(): void
{
}
public function detach()
{
return null;
}
public function getSize(): ?int
{
return 0;
}
public function tell(): int
{
return 0;
}
public function eof(): bool
{
return true;
}
public function isSeekable(): bool
{
return false;
}
public function seek($offset, $whence = SEEK_SET): void
{
}
public function rewind(): void
{
}
public function isWritable(): bool
{
return false;
}
public function write($string): int
{
return 0;
}
public function isReadable(): bool
{
return true;
}
public function read($length): string
{
return '';
}
public function getContents(): string
{
return '';
}
public function getMetadata($key = null)
{
return $key ? null : [];
}
};
}
};

View file

@ -23,7 +23,8 @@ class Config implements ArrayAccess, IteratorAggregate
*/
public function __construct(
private array $options
) {}
) {
}
/**
* Retrieves a configuration value by key.
@ -166,4 +167,4 @@ class Config implements ArrayAccess, IteratorAggregate
{
return new \ArrayIterator($this->options);
}
}
}

View file

@ -7,4 +7,4 @@ namespace Atlas\Exception;
*/
class MissingConfigurationException extends \RuntimeException
{
}
}

View file

@ -7,4 +7,4 @@ namespace Atlas\Exception;
*/
class RouteValidationException extends \RuntimeException
{
}
}

View file

@ -12,7 +12,8 @@ class MatchResult implements \JsonSerializable
private readonly RouteDefinition|null $route = null,
private readonly array $parameters = [],
private readonly array $diagnostics = []
) {}
) {
}
public function isFound(): bool
{

View file

@ -19,7 +19,8 @@ class ModuleLoader
public function __construct(
private readonly Config $config,
private readonly Router|RouteGroup $target
) {}
) {
}
/**
* Loads routes for a given module or modules.
@ -63,7 +64,7 @@ class ModuleLoader
private function loadModuleRoutes(string $routesFile, string|null $prefix = null, string|null $moduleName = null): void
{
$moduleRoutes = require $routesFile;
$options = [];
if ($prefix) {
$options['prefix'] = $prefix;

View file

@ -25,7 +25,8 @@ final class Route
private readonly string $method,
private readonly string $path,
private readonly mixed $handler
) {}
) {
}
/**
* Gets the HTTP method of this route.
@ -56,4 +57,4 @@ final class Route
{
return $this->handler;
}
}
}

View file

@ -65,13 +65,29 @@ class RouteDefinition implements \JsonSerializable, \Serializable
private array $defaults = [],
private string|null $module = null,
private array $attributes = []
) {}
) {
}
public function getMethod(): string { return $this->method; }
public function getPattern(): string { return $this->pattern; }
public function getPath(): string { return $this->path; }
public function getHandler(): mixed { return $this->handler; }
public function getName(): ?string { return $this->name; }
public function getMethod(): string
{
return $this->method;
}
public function getPattern(): string
{
return $this->pattern;
}
public function getPath(): string
{
return $this->path;
}
public function getHandler(): mixed
{
return $this->handler;
}
public function getName(): ?string
{
return $this->name;
}
public function name(string $name): self
{
@ -79,7 +95,10 @@ class RouteDefinition implements \JsonSerializable, \Serializable
return $this;
}
public function getMiddleware(): array { return $this->middleware; }
public function getMiddleware(): array
{
return $this->middleware;
}
public function middleware(string|array $middleware): self
{
@ -91,7 +110,10 @@ class RouteDefinition implements \JsonSerializable, \Serializable
return $this;
}
public function getValidation(): array { return $this->validation; }
public function getValidation(): array
{
return $this->validation;
}
public function valid(array|string $param, array|string $rules = []): self
{
@ -105,7 +127,10 @@ class RouteDefinition implements \JsonSerializable, \Serializable
return $this;
}
public function getDefaults(): array { return $this->defaults; }
public function getDefaults(): array
{
return $this->defaults;
}
public function default(string $param, mixed $value): self
{
@ -113,9 +138,15 @@ class RouteDefinition implements \JsonSerializable, \Serializable
return $this;
}
public function getModule(): ?string { return $this->module; }
public function getModule(): ?string
{
return $this->module;
}
public function getAttributes(): array { return $this->attributes; }
public function getAttributes(): array
{
return $this->attributes;
}
public function attr(string $key, mixed $value): self
{

View file

@ -18,7 +18,8 @@ class RouteGroup
public function __construct(
private array $options = [],
private readonly Router|null $router = null
) {}
) {
}
/**
* Creates a new route group with options and router.
@ -42,7 +43,7 @@ class RouteGroup
if ($this->router) {
return $this->router->registerCustomRoute('GET', $fullPath, $handler, $name, $middleware, $validation, $defaults);
}
return new RouteDefinition('GET', $fullPath, $fullPath, $handler, $name, $middleware, $validation, $defaults);
}
@ -56,7 +57,7 @@ class RouteGroup
if ($this->router) {
return $this->router->registerCustomRoute('POST', $fullPath, $handler, $name, $middleware, $validation, $defaults);
}
return new RouteDefinition('POST', $fullPath, $fullPath, $handler, $name, $middleware, $validation, $defaults);
}
@ -70,7 +71,7 @@ class RouteGroup
if ($this->router) {
return $this->router->registerCustomRoute('PUT', $fullPath, $handler, $name, $middleware, $validation, $defaults);
}
return new RouteDefinition('PUT', $fullPath, $fullPath, $handler, $name, $middleware, $validation, $defaults);
}
@ -84,7 +85,7 @@ class RouteGroup
if ($this->router) {
return $this->router->registerCustomRoute('PATCH', $fullPath, $handler, $name, $middleware, $validation, $defaults);
}
return new RouteDefinition('PATCH', $fullPath, $fullPath, $handler, $name, $middleware, $validation, $defaults);
}
@ -98,7 +99,7 @@ class RouteGroup
if ($this->router) {
return $this->router->registerCustomRoute('DELETE', $fullPath, $handler, $name, $middleware, $validation, $defaults);
}
return new RouteDefinition('DELETE', $fullPath, $fullPath, $handler, $name, $middleware, $validation, $defaults);
}
@ -119,10 +120,10 @@ class RouteGroup
public function fallback(mixed $handler): self
{
$this->options['fallback'] = $handler;
$prefix = $this->options['prefix'] ?? '/';
$middleware = $this->options['middleware'] ?? [];
if ($this->router) {
$this->router->registerCustomRoute('FALLBACK', $this->joinPaths($prefix, '/_fallback'), $handler, null, $middleware)
->attr('_fallback', $handler)
@ -136,7 +137,7 @@ class RouteGroup
{
$fullPath = $this->buildFullPath($path);
$mergedMiddleware = array_merge($this->options['middleware'] ?? [], $middleware);
$route = null;
if ($this->router) {
$route = $this->router->registerCustomRoute($method, $fullPath, $handler, $name, $mergedMiddleware);
@ -179,7 +180,7 @@ class RouteGroup
$prefix = $this->options['prefix'] ?? '';
$newPrefix = $this->joinPaths($prefix, $options['prefix'] ?? '');
$middleware = $this->options['middleware'] ?? [];
$newMiddleware = array_merge($middleware, $options['middleware'] ?? []);
@ -188,7 +189,7 @@ class RouteGroup
$defaults = $this->options['defaults'] ?? [];
$newDefaults = array_merge($defaults, $options['defaults'] ?? []);
$mergedOptions = array_merge($this->options, $options);
$mergedOptions['prefix'] = $newPrefix;
$mergedOptions['middleware'] = $newMiddleware;
@ -267,10 +268,10 @@ class RouteGroup
// But ModuleLoader uses the router directly.
// If we use $this->router->module(), it won't have the group prefix/middleware.
// We should probably allow ModuleLoader to take a "target" which can be a Router or RouteGroup.
// For now, let's just use the router but we have a problem: inheritance.
// A better way is to make RouteGroup have a way to load modules.
$moduleLoader = new ModuleLoader($this->router->getConfig(), $this);
$moduleLoader->load($identifier, $prefix);
}
@ -289,4 +290,4 @@ class RouteGroup
{
return $this->router->getConfig();
}
}
}

View file

@ -34,7 +34,7 @@ class RouteMatcher
$attributes = $this->mergeDefaults($route, $attributes);
return $this->applyAttributes($route, $attributes);
}
// i18n support: check alternative paths
$routeAttributes = $route->getAttributes();
if (isset($routeAttributes['i18n']) && is_array($routeAttributes['i18n'])) {
@ -129,7 +129,7 @@ class RouteMatcher
}
$pattern = $overridePath ? $this->compilePatternFromPath($overridePath, $route) : $this->getPatternForRoute($route);
if (preg_match($pattern, $path, $matches)) {
$attributes = array_filter($matches, 'is_string', ARRAY_FILTER_USE_KEY);
return true;
@ -179,10 +179,10 @@ class RouteMatcher
$pattern = preg_replace_callback('#/\{\{([a-zA-Z0-9_]+)(\?)?\}\}#', function ($matches) use ($validation, $defaults) {
$name = $matches[1];
$optional = (isset($matches[2]) && $matches[2] === '?') || array_key_exists($name, $defaults);
$rules = $validation[$name] ?? [];
$regex = '[^/]+';
// Validation rules support
foreach ((array)$rules as $rule) {
if ($rule === 'numeric' || $rule === 'int') {
@ -199,7 +199,7 @@ class RouteMatcher
if ($optional) {
return '(?:/(?P<' . $name . '>' . $regex . '))?';
}
return '/(?P<' . $name . '>' . $regex . ')';
}, $path);
@ -219,7 +219,7 @@ class RouteMatcher
{
$data = $route->toArray();
$data['attributes'] = array_merge($data['attributes'], $attributes);
return new RouteDefinition(
$data['method'],
$data['pattern'],

View file

@ -119,7 +119,7 @@ class Router
$attributes = [];
$routeMethod = strtoupper($route->getMethod());
$routePath = $route->getPath();
$matchStatus = 'mismatch';
if ($routeMethod !== $method && $routeMethod !== 'REDIRECT') {
$matchStatus = 'method_mismatch';
@ -129,7 +129,7 @@ class Router
$matchStatus = 'matched';
$attributes = array_filter($matches, 'is_string', ARRAY_FILTER_USE_KEY);
$attributes = array_merge($route->getDefaults(), $attributes);
return new MatchResult(true, $route, $attributes, $diagnostics);
}
}
@ -163,7 +163,7 @@ class Router
public function fallback(mixed $handler): self
{
$this->fallbackHandler = $handler;
// Register a special route to carry the global fallback
$this->registerRoute('FALLBACK', '/_fallback', $handler)
->attr('_fallback', $handler)
@ -203,7 +203,7 @@ class Router
foreach ($parameterNames as $index => $name) {
$pattern = '{{' . $name . ($isOptional[$index] === '?' ? '?' : '') . '}}';
if (array_key_exists($name, $parameters)) {
$path = str_replace($pattern, (string)$parameters[$name], $path);
} elseif (array_key_exists($name, $defaults)) {
@ -228,4 +228,4 @@ class Router
$this->loader->load($identifier, $prefix);
return $this;
}
}
}