103 lines
2.1 KiB
PHP
103 lines
2.1 KiB
PHP
<?php
|
|
|
|
|
|
final class URLMapperException extends Exception {}
|
|
|
|
|
|
final class URLMapper
|
|
implements PackageAware
|
|
{
|
|
private $package;
|
|
private $prefix;
|
|
private $configBase;
|
|
|
|
public function __construct( $prefix = null )
|
|
{
|
|
$this->prefix = $prefix;
|
|
$this->configBase = ( $prefix == null ) ? 'urls' : $prefix;
|
|
}
|
|
|
|
public function setPackage( Package $package )
|
|
{
|
|
if ( $this->package !== null ) {
|
|
throw new Exception( 'trying to call setPackage() twice' );
|
|
}
|
|
$this->package = $package;
|
|
}
|
|
|
|
|
|
public function fromPathInfo( )
|
|
{
|
|
if ( array_key_exists( 'PATH_INFO' , $_SERVER ) ) {
|
|
$path = $_SERVER[ 'PATH_INFO' ];
|
|
} else {
|
|
$path = '/' . $this->package->config( $this->configBase . '/default' , 'home' );
|
|
}
|
|
|
|
$this->fromPath( $path );
|
|
}
|
|
|
|
public function fromPath( $path )
|
|
{
|
|
if ( ! preg_match( '/^(\/[a-z0-9]+)+$/' , $path ) ) {
|
|
$this->showPageNotFound( );
|
|
return;
|
|
}
|
|
|
|
if ( $this->prefix == null ) {
|
|
$path = substr( $path , 1 );
|
|
} else {
|
|
$path = $this->prefix . $path;
|
|
}
|
|
try {
|
|
$this->showPageFor( $path );
|
|
} catch ( URLMapperException $e ) {
|
|
$this->showPageNotFound( $path );
|
|
}
|
|
}
|
|
|
|
|
|
private function showPageNotFound( $requestPath )
|
|
{
|
|
$path = $this->package->config( $this->configBase . '/errors/404', 'errors/404' );
|
|
$this->showPageFor( $path . '/' . $requestPath , false );
|
|
}
|
|
|
|
|
|
private function showPageFor( $path )
|
|
{
|
|
$split = split( '/' , $path );
|
|
$extras = array( );
|
|
while ( !empty( $split ) ) {
|
|
$name = join( '_' , $split );
|
|
try {
|
|
$page = Loader::Page( $name );
|
|
break;
|
|
} catch ( LoaderException $e ) {
|
|
array_unshift( $extras , array_pop( $split ) );
|
|
}
|
|
}
|
|
|
|
if ( empty( $split ) ) {
|
|
throw new URLMapperException( $path );
|
|
}
|
|
|
|
$this->handlePage( $path , $page , join( '/' , $extras ) );
|
|
}
|
|
|
|
|
|
private function handlePage( $requestPath , Page $page , $extraPath = '' , $pathFailure = true )
|
|
{
|
|
if ( $page instanceof PathAware ) {
|
|
$success = $page->setExtraPath( $extraPath );
|
|
} else {
|
|
$success = ( $extraPath === '' );
|
|
}
|
|
|
|
if ( $pathFailure && !$success ) {
|
|
$this->showPageNotFound( $requestPath );
|
|
} else {
|
|
$page->handle( );
|
|
}
|
|
}
|
|
}
|