Commit d4ddb05a authored by Taylor Otwell's avatar Taylor Otwell

refactoring. added default controller. added uri class.

parent 320653e8
<?php
class Home_Controller extends Controller {
public function index()
{
return View::make('home.index');
}
}
\ No newline at end of file
......@@ -10,11 +10,11 @@ return array(
| Here is the public API of your application. To add functionality to your
| application, you just add to the array located in this file.
|
| Simply tell Laravel the HTTP verbs and request URIs it should respond to.
| You may respond to the GET, POST, PUT, or DELETE verbs. Enjoy the simplicity
| and elegance of RESTful routing.
| Simply tell Laravel the HTTP verbs and URIs it should respond to. It is a
| breeze to create beautiful applications using the simplicity and elegance
| of Laravel's RESTful routing.
|
| Here is how to respond to a simple GET request to http://example.com/hello:
| Let's respond to a simple GET request to http://example.com/hello:
|
| 'GET /hello' => function()
| {
......@@ -28,7 +28,7 @@ return array(
| return 'Hello World!';
| }
|
| It's easy to allow URI wildcards using the (:num) or (:any) place-holders:
| It's easy to allow URI wildcards using (:num) or (:any):
|
| 'GET /hello/(:any)' => function($name)
| {
......@@ -42,4 +42,4 @@ return array(
return View::make('home.index');
},
);
);
\ No newline at end of file
......@@ -101,6 +101,7 @@ register_shutdown_function(function() use ($handler)
{
if ( ! is_null($error = error_get_last()))
{
die('here');
extract($error, EXTR_SKIP);
$handler(new \ErrorException($message, $type, 0, $file, $line));
......
......@@ -82,7 +82,7 @@ class Form {
*/
protected static function action($action, $https)
{
return HTML::entities(URL::to(((is_null($action)) ? Request::uri() : $action), $https));
return HTML::entities(URL::to(((is_null($action)) ? Request::uri()->get() : $action), $https));
}
/**
......
......@@ -37,6 +37,7 @@ if (Config::$items['session']['driver'] !== '')
* Manually load some core classes that are used on every request
* This allows to avoid using the loader for these classes.
*/
require SYS_PATH.'uri'.EXT;
require SYS_PATH.'input'.EXT;
require SYS_PATH.'request'.EXT;
require SYS_PATH.'response'.EXT;
......@@ -90,7 +91,7 @@ Input::$input = $input;
*/
Routing\Filter::register(require APP_PATH.'filters'.EXT);
list($uri, $method) = array(Request::uri(), Request::method());
list($uri, $method) = array(Request::uri()->get(), Request::method());
$route = IoC::container()->core('routing.router')->route($method, $uri);
......
......@@ -250,7 +250,7 @@ class Paginator {
// We will assume the page links should use HTTPS if the current request
// is also using HTTPS. Since pagination links automatically point to
// the current URI, this makes pretty good sense.
list($uri, $secure) = array(Request::uri(), Request::secure());
list($uri, $secure) = array(Request::uri()->get(), Request::secure());
$appendage = $this->appendage($element, $page);
......
......@@ -3,18 +3,18 @@
class Request {
/**
* The route handling the current request.
* The request URI for the current request.
*
* @var Routing\Route
* @var URI
*/
public static $route;
public static $uri;
/**
* The request URI for the current request.
* The route handling the current request.
*
* @var string
* @var Routing\Route
*/
public static $uri;
public static $route;
/**
* The request data key that is used to indicate a spoofed request method.
......@@ -24,79 +24,36 @@ class Request {
const spoofer = '__spoofer';
/**
* Get the URI for the current request.
*
* Note: This method is the equivalent of calling the URI::get method.
* Get the URI instance for the current request.
*
* @return string
* @return URI
*/
public static function uri()
{
if ( ! is_null(static::$uri)) return static::$uri;
// Sniff the request URI out of the $_SERVER array. The PATH_IFNO
// variable contains the URI without the base URL or index page,
// so we will use that if possible, otherwise we will parse the
// URI out of the REQUEST_URI element.
if (isset($_SERVER['PATH_INFO']))
{
$uri = $_SERVER['PATH_INFO'];
}
elseif (isset($_SERVER['REQUEST_URI']))
{
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
if ($uri === false)
{
throw new \Exception("Invalid request URI. Request terminated.");
}
}
else
{
throw new \Exception("Unable to determine the request URI.");
}
// Remove the application URL and the application index page from
// the request URI. Both of these elements will interfere with the
// routing engine and are extraneous, so they will be removed.
$base = parse_url(Config::$items['application']['url'], PHP_URL_PATH);
if (strpos($uri, $base) === 0)
{
$uri = substr($uri, strlen($base));
}
$index = '/'.Config::$items['application']['index'];
if (trim($index) !== '/' and strpos($uri, $index) === 0)
{
$uri = substr($uri, strlen($index));
}
// Request URIs to the root of the application will be returned
// as a single forward slash. Otherwise, the request URI will be
// returned without leading or trailing slashes.
return static::$uri = (($uri = trim($uri, '/')) == '') ? '/' : $uri;
return (is_null(static::$uri)) ? static::$uri = new URI($_SERVER) : static::$uri;
}
/**
* Get the request format.
*
* The format is determined by essentially taking the "extension" of the URI.
* The format is determined by taking the "extension" of the URI.
*
* @param string $uri
* @return string
*/
public static function format()
public static function format($uri = null)
{
return (($extension = pathinfo(static::uri(), PATHINFO_EXTENSION)) !== '') ? $extension : 'html';
if (is_null($uri)) $uri = static::uri()->get();
return (($extension = pathinfo($uri, PATHINFO_EXTENSION)) !== '') ? $extension : 'html';
}
/**
* Get the request method.
*
* Typically, this will be the value of the REQUEST_METHOD $_SERVER variable.
* However, when the request is being spoofed by a hidden form value, the request
* method will be stored in the $_POST array.
* This will usually be the value of the REQUEST_METHOD $_SERVER variable
* However, when the request method is spoofed using a hidden form value,
* the method will be stored in the $_POST array.
*
* @return string
*/
......@@ -122,10 +79,6 @@ class Request {
/**
* Determine if the request method is being spoofed by a hidden Form element.
*
* Hidden elements are used to spoof PUT and DELETE requests since they are not supported
* by HTML forms. If the request is being spoofed, Laravel considers the spoofed request
* method the actual request method throughout the framework.
*
* @return bool
*/
public static function spoofed()
......
......@@ -122,11 +122,16 @@ class Router {
foreach ($routes as $keys => $callback)
{
// Formats are appended to the route key as a regular expression.
// It will look something like: "(\.(json|xml|html))?"
$formats = $this->provides($callback);
// Only check routes that have multiple URIs or wildcards since other
// routes would have been caught by the check for literal matches.
if (strpos($keys, '(') !== false or strpos($keys, ',') !== false)
// We also need to check routes with "provides" clauses.
if ($this->fuzzy($keys) or ! is_null($formats))
{
if ( ! is_null($route = $this->match($destination, $keys, $callback)))
if ( ! is_null($route = $this->match($destination, $keys, $callback, $formats)))
{
return Request::$route = $route;
}
......@@ -136,6 +141,21 @@ class Router {
return Request::$route = $this->controller($method, $uri, $destination);
}
/**
* Determine if the route contains elements that forbid literal matches.
*
* Any route key containing a regular expression, wildcard, or multiple
* URIs cannot be matched using a literal string check, but must be
* checked using regular expressions.
*
* @param string $keys
* @return bool
*/
protected function fuzzy($keys)
{
return strpos($keys, '(') !== false or strpos($keys, ',') !== false;
}
/**
* Attempt to match a given route destination to a given route.
*
......@@ -146,20 +166,18 @@ class Router {
* @param string $destination
* @param array $keys
* @param mixed $callback
* @param array $formats
* @return mixed
*/
protected function match($destination, $keys, $callback)
protected function match($destination, $keys, $callback, $formats)
{
// Append the provided formats to the route as an optional regular expression.
// This should make the route look something like: "user(\.(json|xml|html))?"
$formats = ( ! is_null($formats)) ? '(\.('.implode('|', $formats).'))?' : '';
foreach (explode(', ', $keys) as $key)
{
// Append the provided formats to the route as an optional regular expression.
// This should make the route look something like: "user(\.(json|xml|html))?"
if ( ! is_null($formats = $this->provides($callback)))
{
$key .= '(\.('.implode('|', $formats).'))?';
}
if (preg_match('#^'.$this->wildcards($key).'$#', $destination))
if (preg_match('#^'.$this->wildcards($key).$formats.'$#', $destination))
{
return new Route($keys, $callback, $this->parameters($destination, $key));
}
......@@ -185,19 +203,13 @@ class Router {
if ( ! is_null($key = $this->controller_key($segments)))
{
// Create the controller name for the current request. This controller
// name will be returned by the anonymous route we will create. Instead
// of using directory slashes, dots will be used to specify the controller
// location with the controllers directory.
// Extract the controller name from the URI segments.
$controller = implode('.', array_slice($segments, 0, $key));
// Now that we have the controller path and name, we can slice the controller
// section of the URI from the array of segments.
// Remove the controller name from the URI.
$segments = array_slice($segments, $key);
// Extract the controller method from the URI segments. If no more segments
// are remaining after slicing off the controller, the "index" method will
// be used as the default controller method.
// Extract the controller method from the remaining segments.
$method = (count($segments) > 0) ? array_shift($segments) : 'index';
return new Route($destination, $controller.'@'.$method, $segments);
......@@ -206,12 +218,12 @@ class Router {
/**
* Search the controllers for the application and determine if an applicable
* controller exists for the current request.
* controller exists for the current request to the application.
*
* If a controller is found, the array key for the controller name in the URI
* segments will be returned by the method, otherwise NULL will be returned.
* The deepest possible matching controller will be considered the controller
* that should handle the request.
* The deepest possible controller will be considered the controller that
* should handle the request.
*
* @param array $segments
* @return int
......@@ -276,7 +288,21 @@ class Router {
*/
protected function parameters($uri, $route)
{
return array_values(array_intersect_key(explode('/', $uri), preg_grep('/\(.+\)/', explode('/', $route))));
list($uri, $route) = array(explode('/', $uri), explode('/', $route));
$count = count($route);
$parameters = array();
for ($i = 0; $i < $count; $i++)
{
if (preg_match('/\(.+\)/', $route[$i]))
{
$parameters[] = $uri[$i];
}
}
return $parameters;
}
}
\ No newline at end of file
<?php namespace Laravel;
class URI {
/**
* The request URI for the current request.
*
* @var string
*/
protected $uri;
/**
* The $_SERVER global array for the current request.
*
* @var array
*/
protected $server;
/**
* Create a new instance of the URI class.
*
* @param array $server
* @return void
*/
public function __construct($server)
{
$this->server = $server;
}
/**
* Get the request URI for the current request.
*
* @return string
*/
public function get()
{
if (is_null($this->uri))
{
$uri = parse_url($this->server['REQUEST_URI'], PHP_URL_PATH);
$this->uri = $this->format($this->clean($uri));
}
return $this->uri;
}
/**
* Remove extraneous information from the given request URI.
*
* @param string $uri
* @return string
*/
protected function clean($uri)
{
// The base application URL is removed first. If the application is being
// served out of a sub-directory of the web document root, we need to get
// rid of the folders that are included in the URI.
$uri = $this->remove($uri, parse_url(Config::$items['application']['url'], PHP_URL_PATH));
// Next, the application index file is removed. The index file has nothing
// to do with how the request is routed to a closure or controller, so it
// can be safely removed from the URI.
if (($index = '/'.Config::$items['application']['index']) !== '/')
{
$uri = $this->remove($uri, $index);
}
// We don't consider the request format to be a part of the request URI.
// The format merely determines in which format the requested resource
// should be returned to the client.
return rtrim($uri, '.'.Request::format($uri));
}
/**
* Remove a string from the beginning of a URI.
*
* @param string $uri
* @param string $remove
* @return string
*/
protected function remove($uri, $remove)
{
return (strpos($uri, $remove) === 0) ? substr($uri, strlen($remove)) : $uri;
}
/**
* Format the URI for use throughout the framework.
*
* If the request is to the root of the application, a single forward slash
* will be returned. Otherwise, the URI will be returned with all leading
* and trailing slashes removed.
*
* @param string $uri
* @return string
*/
protected function format($uri)
{
return (($uri = trim($uri, '/')) !== '') ? $uri : '/';
}
}
\ No newline at end of file
......@@ -55,7 +55,14 @@ class URL {
{
if (is_null($https)) $https = Request::secure();
return str_replace(Config::$items['application']['index'].'/', '', static::to($url, $https));
$url = static::to($url, $https);
if (($index = Config::$items['application']['index']) !== '')
{
$url = str_replace($index.'/', '', $url);
}
return $url;
}
/**
......
......@@ -20,13 +20,6 @@ define('START_TIME', microtime(true));
|--------------------------------------------------------------------------
| Laravel Installation Paths
|--------------------------------------------------------------------------
|
| Here you may specify the location of the various Laravel framework
| directories for your installation.
|
| Of course, these are already set to the proper default values, so you do
| not need to change them if you have not modified the directory structure.
|
*/
$application = '../application';
......
......@@ -10,39 +10,13 @@ class RequestTest extends PHPUnit_Framework_TestCase {
Laravel\Request::$uri = null;
}
/**
* @expectedException Exception
*/
public function test_exception_thrown_if_uri_cant_be_determined()
{
Laravel\Request::uri();
}
public function test_uri_method_returns_path_info_if_set()
{
$_SERVER['PATH_INFO'] = 'something';
$this->assertEquals('something', Laravel\Request::uri());
}
/**
* @dataProvider requestUriProvider
*/
public function test_correct_uri_is_returned_when_request_uri_is_used($uri, $expectation)
{
$_SERVER['REQUEST_URI'] = $uri;
$this->assertEquals($expectation, Laravel\Request::uri());
}
public function test_format_returns_the_extension_of_the_request_uri()
{
$_SERVER['PATH_INFO'] = 'profile.json';
$this->assertEquals('json', Laravel\Request::format());
}
public function test_format_returns_html_if_no_format_is_available()
{
$_SERVER['PATH_INFO'] = 'profile';
$this->assertEquals('html', Laravel\Request::format());
$this->assertEquals($expectation, Laravel\Request::uri()->get());
}
public function test_request_method_returns_spoofed_method_if_uri_is_spoofed()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment