Skip to content

Instantly share code, notes, and snippets.

@nerdsrescueme
Created November 28, 2011 18:20
Show Gist options
  • Save nerdsrescueme/1401391 to your computer and use it in GitHub Desktop.
Save nerdsrescueme/1401391 to your computer and use it in GitHub Desktop.
Atom dispatch
<?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