arse/includes/core/urls.inc.php

104 lines
2.1 KiB
PHP
Raw Normal View History

<?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( );
}
}
}