Created
November 28, 2011 18:20
-
-
Save nerdsrescueme/1401391 to your computer and use it in GitHub Desktop.
Atom dispatch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Structural design pattern namespace. | |
* | |
* Structural design patterns are design patterns that ease the design by | |
* identifying a simple way to realize relationships between entities. | |
* | |
* @package Atom | |
* @subpackage Design | |
*/ | |
namespace Atom\Design\Structural; | |
// Aliasing rules | |
use Atom\Config; | |
/** | |
* Front Controller Pattern | |
* | |
* The Front controller pattern is designed for centralized request logic. A | |
* front controller can help eliminate duplicate code on a series of requests | |
* through the front controller and factoring the duplicate code from the | |
* requests into the front controller. | |
* | |
* [!!] Althought MVC isn't directly related to the FrontController pattern, the | |
* current implementation of this class executes it. This may change in the | |
* future, but as for now, please understand what you're getting into when you | |
* use this pattern. | |
* | |
* @package Atom | |
* @subpackage Design | |
*/ | |
class FrontController | |
{ | |
/** | |
* The request URI | |
* | |
* The request URI will always be prepended with a slash. As a result, if | |
* the request is to the root of the application, a single forward slash | |
* will be returned. | |
* | |
* @return string | |
*/ | |
protected static $uri; | |
/** | |
* Magic method called when a class is first encountered by the Loader | |
* during file inclusion. | |
* | |
* ## Usage | |
* | |
* $uri = FrontController::getUri(); | |
* | |
* @return void No value is returned | |
*/ | |
public static function getUri() | |
{ | |
if(static::$uri == null) | |
{ | |
if(isset($_SERVER['PATH_INFO'])) | |
{ | |
$uri = $_SERVER['PATH_INFO']; | |
} | |
elseif(isset($_SERVER['REQUEST_URI'])) | |
{ | |
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); | |
} | |
else | |
{ | |
throw new \Exception('Unable to determine the request URI'); | |
} | |
if($uri === false) | |
{ | |
throw new \Exception('Malformed request URI. Request terminated.'); | |
} | |
if(strpos($uri, $base = parse_url(Config::get('application.url'), PHP_URL_PATH)) === 0) | |
{ | |
$uri = substr($uri, strlen($base)); | |
} | |
if(strpos($uri, $index = '/index.php') === 0) | |
{ | |
$uri = substr($uri, strlen($index)); | |
} | |
static::$uri = (($uri = trim($uri, '/')) == '') ? '/' : '/'.$uri; | |
} | |
return static::$uri; | |
} | |
/** | |
* The dispatcher extracts the active URI and routes to a namespaced | |
* Controller for further handling. | |
* | |
* [!!] This method could use some serious optimization, and modularity. | |
* | |
* ## Usage | |
* | |
* $request = FrontController::dispatch(); | |
* | |
* Once you've dispatched your request, you can handle everything after | |
* as you would a \Http\Response. | |
* | |
* @return Response Returns the response instance for further execution | |
*/ | |
public static function dispatch() | |
{ | |
$url = parse_url('http://ignore.me'.static::getUri()); | |
$url['method'] = strtoupper($_SERVER['REQUEST_METHOD']); | |
$url['query'] = parse_str($url['query']); | |
$url['http'] = $url['method'].' '$url['path']; | |
$url['route'] = $url['path']; | |
$response = \Atom\Http\Response::make(); | |
// Check for default route... | |
if($url['path'] == '/' and !$route = Config::get('routes._default_', false)) | |
{ | |
throw new \Atom\Http\Exception(404, $response); | |
} | |
else | |
{ | |
// Do it! | |
} | |
// Check for HTTP Verb route | |
if(($route = Config::get('routes.'.$url['http'], false)) !== false) | |
{ | |
// Do it! | |
} | |
// Check for normal route | |
if(($route = Config::get('routes.'.$url['route'], false)) !== false) | |
{ | |
// Do it! | |
} | |
// Check for MVC route | |
preg_match("/([^/]+)/uis", "item", $url['path'], $segments); | |
array_shift($segments); // Remove full string match. | |
if(!strcasecmp($segments[0], APPLICATION_NS) and is_dir(LIBRARY_PATH.'/'.$segments[0])) | |
{ | |
$path = LIBRARY_PATH.'/'.strtolower(array_shift($segments)).'/controller/'; | |
} | |
else | |
{ | |
$path = LIBRARY_PATH.'/'.strtolower(APPLICATION_NS).'/controller/'; | |
} | |
$possibilities = array(); | |
while(count($segments) > 0 and is_dir($path.$segments[0])) | |
{ | |
$path .= $segments[0].'/'; | |
$possibilities []= array_shift($segments); | |
} | |
if(!file_exists($path.$segments[0].'.php') | |
{ | |
throw new \Atom\Http\Exception(404, $response); | |
} | |
$possibilities []= array_shift($segments); | |
$controller = ''; | |
foreach($possibilities as $p) | |
{ | |
$controller .= ucfirst($p).'\\'; | |
} | |
$controller = rtrim($controller, '\\'); | |
$action = 'action'.ucfirst(array_shift($segments)); | |
class_exists($controller) and $controller = new $controller($response); | |
if(!is_object($controller) or !method_exists($controller, $action)) | |
{ | |
throw new \Atom\Http\Exception(404, $response); | |
} | |
$controller->before(); | |
$response->setBody(call_user_func_array(array($controller, $action), $segments)); | |
$controller->after(); | |
return $response; | |
} | |
} | |
/* End of file frontcontroller.php */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment