refactor: implement milestone 5 - code quality & error standardization

This commit is contained in:
Funky Waddle 2026-02-14 17:27:25 -06:00
parent ea23140a40
commit d8db903d2e
4 changed files with 109 additions and 13 deletions

View file

@ -1,12 +0,0 @@
<?php
namespace Atlas\Exception;
/**
* Exception thrown when no route matches the request for matching or URL generation.
*
* @extends \RuntimeException
*/
class NotFoundRouteException extends \RuntimeException
{
}

View file

@ -5,6 +5,9 @@ namespace Atlas\Exception;
/** /**
* Exception thrown when a requested route is not found. * Exception thrown when a requested route is not found.
* *
* This may occur during matching if no route corresponds to the request,
* or during URL generation if the requested route name is not registered.
*
* @extends \RuntimeException * @extends \RuntimeException
*/ */
class RouteNotFoundException extends \RuntimeException class RouteNotFoundException extends \RuntimeException

45
src/Router/PathHelper.php Normal file
View file

@ -0,0 +1,45 @@
<?php
namespace Atlas\Router;
/**
* Helper trait for path normalization across routing components.
*/
trait PathHelper
{
/**
* Normalizes a URI path by ensuring it has a leading slash and no trailing slash.
*
* @param string $path The path to normalize
* @return string The normalized path
*/
protected function normalizePath(string $path): string
{
$normalized = trim($path, '/');
if (empty($normalized)) {
return '/';
}
return '/' . $normalized;
}
/**
* Joins two path segments ensuring proper slash separation.
*
* @param string $prefix The path prefix
* @param string $path The path suffix
* @return string The joined and normalized path
*/
protected function joinPaths(string $prefix, string $path): string
{
$prefix = rtrim($prefix, '/');
$path = ltrim($path, '/');
if (empty($prefix)) {
return $this->normalizePath($path);
}
return $this->normalizePath($prefix . '/' . $path);
}
}

View file

@ -0,0 +1,60 @@
<?php
namespace Atlas\Tests\Unit;
use Atlas\Router\PathHelper;
use PHPUnit\Framework\TestCase;
class PathHelperTest extends TestCase
{
private $helper;
protected function setUp(): void
{
$this->helper = new class {
use PathHelper;
public function testNormalize(string $path): string
{
return $this->normalizePath($path);
}
public function testJoin(string $prefix, string $path): string
{
return $this->joinPaths($prefix, $path);
}
};
}
public function testNormalizePathEnsuresLeadingSlash(): void
{
$this->assertSame('/test', $this->helper->testNormalize('test'));
$this->assertSame('/test', $this->helper->testNormalize('/test'));
}
public function testNormalizePathRemovesTrailingSlash(): void
{
$this->assertSame('/test', $this->helper->testNormalize('test/'));
$this->assertSame('/test', $this->helper->testNormalize('/test/'));
}
public function testNormalizePathHandlesEmptyOrSlash(): void
{
$this->assertSame('/', $this->helper->testNormalize(''));
$this->assertSame('/', $this->helper->testNormalize('/'));
$this->assertSame('/', $this->helper->testNormalize('///'));
}
public function testJoinPathsCombinesCorrectly(): void
{
$this->assertSame('/api/users', $this->helper->testJoin('/api', 'users'));
$this->assertSame('/api/users', $this->helper->testJoin('/api/', '/users'));
$this->assertSame('/api/users', $this->helper->testJoin('api', 'users'));
}
public function testJoinPathsHandlesRootPrefix(): void
{
$this->assertSame('/users', $this->helper->testJoin('/', 'users'));
$this->assertSame('/users', $this->helper->testJoin('', 'users'));
}
}