Skip to content
This repository has been archived by the owner on Nov 2, 2018. It is now read-only.

Commit

Permalink
Merge branch 'feature/move-route-execution-from-router-to-route' into…
Browse files Browse the repository at this point in the history
… develop
  • Loading branch information
hassankhan committed Feb 20, 2014
2 parents a86b255 + 7407b6f commit 20d9643
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 107 deletions.
11 changes: 11 additions & 0 deletions library/Zepto/Route.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,17 @@ public function __construct($pattern, \Closure $callback)
$this->callback = $callback;
}

/**
* Executes a route's callback and returns the result. Simple as that.
*
* @param array $params
* @return string
*/
public function execute($params = array())
{
return call_user_func_array($this->callback, $params);
}

/**
* ACCESSORS
*/
Expand Down
35 changes: 35 additions & 0 deletions library/Zepto/Route/ErrorRoute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace Zepto\Route;

/**
* ErrorRoute
*
* This route is executed on any application error.
*
* @package Zepto
* @subpackage Route
* @author Hassan Khan <contact@hassankhan.me>
* @link https://github.com/hassankhan/Zepto
* @license MIT
* @since 0.7
*/
class ErrorRoute extends \Zepto\Route
{

/**
* Initializes the route by creating a regex pattern from the provided URL,
* and assigns the callable function for this route
*
* @param string $url
* @codeCoverageIgnore
*/
public function __construct($url = '', $title, $body)
{
$callback = function() use ($title, $body) {
return sprintf('<html><head><title>%s</title><style>body{margin:0;padding:30px;font:12px/1.5 Helvetica,Arial,Verdana,sans-serif;}h1{margin:0;font-size:48px;font-weight:normal;line-height:48px;}strong{display:inline-block;width:65px;}</style></head><body><h1>%s</h1><p>%s</p></body></html>', $title, $title, $body);
};
parent::__construct($url, $callback);
}

}
131 changes: 76 additions & 55 deletions library/Zepto/Router.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ class Router
*
* @var Route[]
*/
protected $routes = array();
protected $routes;

/**
* Callback function to execute when no matching URL is found
Expand Down Expand Up @@ -230,14 +230,20 @@ public function match($url, $http_method = self::METHOD_GET)
* Runs the router matching engine and then calls the matching route's
* callback. otherwise execute the not found handler
*
* @return
* @return bool
* @throws \RuntimeException If no routes exist in the routing table
*/
public function run()
{
// If no routes have been added, then throw an exception
if (empty($this->routes)) {
throw new \RuntimeException('No routes exist in the routing table. Add some');
try {
if (empty($this->routes)) {
throw new \RuntimeException('No routes exist in the routing table. Add some');
}
}
catch (\Exception $e) {
$this->error($e);
return FALSE;
}

// Try and get a matching route for the current URL
Expand All @@ -248,34 +254,57 @@ public function run()

// Call not found handler if no match was found
if ($route === null) {
$this->current_http_status = \Symfony\Component\HttpFoundation\Response::HTTP_NOT_FOUND;
$this->not_found();
return FALSE;
}
// If route is a valid Route object, then try and execute its callback
else {

// Set current route
$this->current_route = $route;
// Set current route
$this->current_route = $route;

// Get parameters from request
$params = $this->parse_parameters($route);
// Get parameters from request
$params = $this->parse_parameters($route);

// Try to execute callback for route, if it fails, catch the exception
// and generate a HTTP 500 error
try {
$this->current_http_status = \Symfony\Component\HttpFoundation\Response::HTTP_OK;
// Try to execute callback for route, if it fails, catch the exception and generate a HTTP 500 error
try {
$this->current_http_status = \Symfony\Component\HttpFoundation\Response::HTTP_OK;

// Set response content
$this->response->setContent(call_user_func_array($route->callback(), $params));
// Set response content
$this->response->setContent($route->execute($params));

// Send response
$this->response->send();
}
catch (\Exception $e) {
$this->current_http_status = \Symfony\Component\HttpFoundation\Response::HTTP_INTERNAL_SERVER_ERROR;
$this->error($e);
// Send response
$this->response->send();
return TRUE;
}
catch (\Exception $e) {
$this->error($e);
return FALSE;
}
}

/**
* Redirects to another URL
*
* @param string $url
* @return bool
*/
public function redirect($url)
{
// If no URL is given, throw exception
try {
if (empty($url)) {
throw new \InvalidArgumentException('No URL given');
}
}
catch (\Exception $e) {
$this->error($e);
return FALSE;
}

// Set redirect status codes and location
$this->current_http_status = \Symfony\Component\HttpFoundation\Response::HTTP_FOUND;
$this->response->setStatusCode($this->current_http_status);
$this->response->headers->set('Location', $url);
return TRUE;
}

/**
Expand Down Expand Up @@ -333,16 +362,18 @@ public function error($arg = null)
$this->error_handler = $arg;
}
else {
// Set HTTP status on router
$this->current_http_status = \Symfony\Component\HttpFoundation\Response::HTTP_INTERNAL_SERVER_ERROR;

// Execute error handler and set result as response content
if (is_callable($this->error_handler)) {
$this->response->setContent(call_user_func($this->error_handler, $arg));
}
else {
$this->response->setContent(call_user_func(array($this, 'default_error_handler'), $arg));
}
$result = is_callable($this->error_handler) === TRUE
? call_user_func($this->error_handler, $arg)
: $this->default_error_handler($arg)->execute();

$this->response->setContent($result);

// Set response's status code
$this->response->setStatusCode(\Symfony\Component\HttpFoundation\Response::HTTP_INTERNAL_SERVER_ERROR);
$this->response->setStatusCode($this->current_http_status);

// Send response
$this->response->send();
Expand All @@ -365,13 +396,16 @@ public function not_found($callback = null)
$this->not_found_handler = $callback;
}
else {
// Set HTTP status on router
$this->current_http_status = \Symfony\Component\HttpFoundation\Response::HTTP_NOT_FOUND;

// Execute not found handler and set result as response content
if (is_callable($this->not_found_handler)) {
$this->response->setContent(call_user_func($this->not_found_handler));
}
else {
$this->response->setContent(call_user_func(array($this, 'default_not_found_handler')));
}
$result = is_callable($this->not_found_handler) === TRUE
? call_user_func($this->not_found_handler)
: $this->default_not_found_handler()->execute();

$this->response->setContent($result);

// Set response's status code
$this->response->setStatusCode($this->current_http_status);

Expand All @@ -380,6 +414,10 @@ public function not_found($callback = null)
}
}

/**
* HELPERS
*/

/**
* Default callback for any 404 errors
*
Expand All @@ -388,7 +426,7 @@ public function not_found($callback = null)
*/
protected function default_not_found_handler()
{
return $this->generate_error_template('Page Not Found', "Couldn't find your, like, page, dude");
return new Route\ErrorRoute('/404', 'Page Not Found', "Couldn't find your, like, page, dude");
}

/**
Expand All @@ -401,13 +439,9 @@ protected function default_not_found_handler()
*/
protected function default_error_handler(\Exception $error)
{
return $this->generate_error_template('Server Error', $error->getMessage());
return new Route\ErrorRoute('/500', 'Server Error', $error->getMessage());
}

/**
* HELPER FUNCTIONS
*/

/**
* Parses parameters from URI as per the given route's pattern
*
Expand All @@ -431,17 +465,4 @@ protected function parse_parameters(Route $route)
return $params;
}

/**
* Returns a standard template for error messages. Thanks, Slim
*
* @param string $title
* @param string $body
* @return string
* @codeCoverageIgnore
*/
protected function generate_error_template($title, $body)
{
return sprintf('<html><head><title>%s</title><style>body{margin:0;padding:30px;font:12px/1.5 Helvetica,Arial,Verdana,sans-serif;}h1{margin:0;font-size:48px;font-weight:normal;line-height:48px;}strong{display:inline-block;width:65px;}</style></head><body><h1>%s</h1><p>%s</p></body></html>', $title, $title, $body);
}

}
15 changes: 7 additions & 8 deletions library/Zepto/Zepto.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,19 +147,15 @@ function($c) use ($settings) {
}

/**
* Executes router and returns result of callback function for specified route
* Executes router and returns true for a successful route,
*
* @return
* @return bool|null
*/
public function run()
{
$this->run_hooks('before_response_send');
try {
return $this->app['router']->run();
} catch (\Exception $e) {
$this->app['router']->error($e);
}
$this->run_hooks('after_response_send');
return $this->app['router']->run();
// $this->run_hooks('after_response_send');
}

/**
Expand Down Expand Up @@ -256,6 +252,9 @@ protected function setup_router()
// Render template with Twig
return $app['twig']->render($template_name, $options);
});

// If a file's name is 404.md or 500.md, use that to set an ErrorRoute with them

}
}

Expand Down
11 changes: 10 additions & 1 deletion tests/Zepto/RouteTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class RouteTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
$this->route = new Route('/get/<:id|[0-9]>', function() {
echo 'Test callback';
return 'Test callback';
});
}

Expand All @@ -30,6 +30,15 @@ protected function tearDown()
{
}

/**
* @covers Zepto\Route::execute()
*/
public function testExecute()
{
$expected = $this->route->execute();
$this->assertEquals($expected, 'Test callback');
}

/**
* @covers Zepto\Route::url
*/
Expand Down

0 comments on commit 20d9643

Please sign in to comment.