Commit 8dfb50c8 by Taylor Otwell

opened up bundles to live anywhere and respond to any URI.'

parent d3d3ffc1
<?php
return array();
\ No newline at end of file
...@@ -7,21 +7,36 @@ class Bundle { ...@@ -7,21 +7,36 @@ class Bundle {
* *
* @var array * @var array
*/ */
protected static $bundles; public static $bundles = array();
/** /**
* A cache of the parsed bundle elements. * A cache of the parsed bundle elements.
* *
* @var array * @var array
*/ */
protected static $elements = array(); public static $elements = array();
/** /**
* All of the bundles that have been started. * All of the bundles that have been started.
* *
* @var array * @var array
*/ */
protected static $started = array(); public static $started = array();
/**
* Register a bundle for the application.
*
* @param string $bundle
* @param string $location
* @param string $handles
* @return void
*/
public static function register($bundle, $location, $handles = null)
{
$location = BUNDLE_PATH.rtrim($location, DS).DS;
static::$bundles[$bundle] = compact('location', 'handles');
}
/** /**
* Load a bundle by running it's start-up script. * Load a bundle by running it's start-up script.
...@@ -72,18 +87,21 @@ class Bundle { ...@@ -72,18 +87,21 @@ class Bundle {
} }
/** /**
* Determine if the given bundle is "routable". * Determine which bundle handles the given URI.
* *
* A bundle is considered routable if it has a controller directory or a routes file. * If no bundle is assigned to handle the URI, the default bundle is returned.
* *
* @param string $bundle * @param string $bundle
* @return bool * @return string
*/ */
public static function routable($bundle) public static function handles($uri)
{ {
$path = static::path($bundle); foreach (static::$bundles as $key => $value)
{
if (starts_with($value['handles'], $uri)) return $key;
}
return is_dir($path.'controllers/') or file_exists($path.'routes'.EXT); return DEFAULT_BUNDLE;
} }
/** /**
...@@ -146,7 +164,7 @@ class Bundle { ...@@ -146,7 +164,7 @@ class Bundle {
*/ */
public static function path($bundle) public static function path($bundle)
{ {
return ($bundle != DEFAULT_BUNDLE) ? BUNDLE_PATH.strtolower($bundle).DS : APP_PATH; return ($bundle == DEFAULT_BUNDLE) ? APP_PATH : static::$bundles[$bundle]['location'];
} }
/** /**
...@@ -267,30 +285,24 @@ class Bundle { ...@@ -267,30 +285,24 @@ class Bundle {
} }
/** /**
* Detect all of the existing bundles in the application. * Get the information for a given bundle.
*
* @param string $bundle
* @return object
*/
public static function get($bundle)
{
return (object) array_get(static::$bundles, $bundle);
}
/**
* Get all of the installed bundle names.
* *
* @return array * @return array
*/ */
public static function all() public static function all()
{ {
if (is_array(static::$bundles)) return static::$bundles; return array_keys(static::$bundles);
$bundles = array();
$files = glob(BUNDLE_PATH.'*');
// When open_basedir is enabled the glob function returns false on
// an empty array. We'll check for this and return an empty array
// if the bundle directory doesn't have any bundles.
if ($files !== false)
{
foreach (array_filter($files, 'is_dir') as $bundle)
{
$bundles[] = basename($bundle);
}
}
return static::$bundles = $bundles;
} }
} }
\ No newline at end of file
...@@ -138,4 +138,18 @@ Autoloader::$mappings = array( ...@@ -138,4 +138,18 @@ Autoloader::$mappings = array(
* having to worry about the namespacing. The developer is also * having to worry about the namespacing. The developer is also
* free to remove aliases when they extend core classes. * free to remove aliases when they extend core classes.
*/ */
Autoloader::$aliases = Config::get('application.aliases'); Autoloader::$aliases = Config::get('application.aliases');
\ No newline at end of file
/**
* Register all of the bundles that are defined in the bundle info
* file within the bundles directory. This informs the framework
* where the bundle lives and which URIs it responds to.
*/
$bundles = require BUNDLE_PATH.'bundles'.EXT;
foreach ($bundles as $key => $value)
{
$handles = array_get($value, 'handles');
Bundle::register($key, $value['location'], $handles);
}
\ No newline at end of file
...@@ -132,16 +132,6 @@ unset($input[Request::spoofer]); ...@@ -132,16 +132,6 @@ unset($input[Request::spoofer]);
Input::$input = $input; Input::$input = $input;
/** /**
* Start all of the bundles that are specified in the configuration
* array of auto-loaded bundles. This lets the developer have an
* easy way to load bundles for every request.
*/
foreach (Config::get('application.bundles') as $bundle)
{
Bundle::start($bundle);
}
/**
* Load the "application" bundle. Though the application folder is * Load the "application" bundle. Though the application folder is
* not typically considered a bundle, it is started like one and * not typically considered a bundle, it is started like one and
* essentially serves as the "default" bundle. * essentially serves as the "default" bundle.
...@@ -149,13 +139,11 @@ foreach (Config::get('application.bundles') as $bundle) ...@@ -149,13 +139,11 @@ foreach (Config::get('application.bundles') as $bundle)
Bundle::start(DEFAULT_BUNDLE); Bundle::start(DEFAULT_BUNDLE);
/** /**
* If the first segment of the URI corresponds with a bundle we'll * Start all of the bundles that are specified in the configuration
* start that bundle. By convention, bundles handle all URIs which * array of auto-loaded bundles. This lets the developer have an
* begin with their bundle name. * easy way to load bundles for every request.
*/ */
$bundle = URI::segment(1); foreach (Config::get('application.bundles') as $bundle)
if ( ! is_null($bundle) and Bundle::routable($bundle))
{ {
Bundle::start($bundle); Bundle::start($bundle);
} }
......
<?php namespace Laravel\Routing; use Closure, Laravel\Bundle; <?php namespace Laravel\Routing; use Closure, Laravel\Str, Laravel\Bundle;
class Router { class Router {
...@@ -128,6 +128,12 @@ class Router { ...@@ -128,6 +128,12 @@ class Router {
*/ */
public static function route($method, $uri) public static function route($method, $uri)
{ {
// First we will make sure the bundle that handles the given URI has
// been started for the current request. Bundles may handle any URI
// as long as it begins with the string in the "handles" item of
// the bundle's registration array.
Bundle::start($bundle = Bundle::handles($uri));
// All route URIs begin with the request method and have a leading // All route URIs begin with the request method and have a leading
// slash before the URI. We'll put the request method and URI in // slash before the URI. We'll put the request method and URI in
// that format so we can easily check for literal matches. // that format so we can easily check for literal matches.
...@@ -139,10 +145,44 @@ class Router { ...@@ -139,10 +145,44 @@ class Router {
} }
// If we can't find a literal match, we'll iterate through all of // If we can't find a literal match, we'll iterate through all of
// the registered routes attempting to find a matching route that // the registered routes to find a matching route that uses some
// uses wildcards or regular expressions. // regular expressions or wildcards.
if ( ! is_null($route = static::match($destination)))
{
return $route;
}
// If the bundle handling the request is not the default bundle,
// we want to remove the root "handles" string from the URI so
// it will not interfere with searching for a controller.
//
// If we left it on the URI, the root controller for the bundle
// would need to be nested in directories matching the clause.
// This will not intefere with the Route::handles method
// as the destination is used to set the route's URIs.
if ($bundle !== DEFAULT_BUNDLE)
{
$uri = str_replace(Bundle::get($bundle)->handles, '', $uri);
$uri = ltrim($uri, '/');
}
return static::controller($bundle, $method, $destination, Str::segments($uri));
}
/**
* Iterate through every route to find a matching route.
*
* @param string $destination
* @return Route
*/
protected static function match($destination)
{
foreach (static::$routes as $route => $action) foreach (static::$routes as $route => $action)
{ {
// We only need to check routes with regular expressions since
// all other routes would have been able to be caught by the
// check for literal matches we just did.
if (strpos($route, '(') !== false) if (strpos($route, '(') !== false)
{ {
$pattern = '#^'.static::wildcards($route).'$#'; $pattern = '#^'.static::wildcards($route).'$#';
...@@ -153,14 +193,6 @@ class Router { ...@@ -153,14 +193,6 @@ class Router {
} }
} }
} }
// If there are no literal matches and no routes that match the
// request, we'll use convention to search for a controller to
// handle the request. If no controller can be found, the 404
// error response will be returned.
$segments = array_diff(explode('/', trim($uri, '/')), array(''));
return static::controller(DEFAULT_BUNDLE, $method, $destination, $segments);
} }
/** /**
...@@ -179,7 +211,7 @@ class Router { ...@@ -179,7 +211,7 @@ class Router {
// use the default method, which is "index". // use the default method, which is "index".
if (count($segments) == 0) if (count($segments) == 0)
{ {
$uri = ($bundle == DEFAULT_BUNDLE) ? '/' : "/{$bundle}"; $uri = ($bundle == DEFAULT_BUNDLE) ? '/' : '/'.Bundle::get($bundle)->handles;
$action = array('uses' => Bundle::prefix($bundle).'home@index'); $action = array('uses' => Bundle::prefix($bundle).'home@index');
...@@ -188,23 +220,6 @@ class Router { ...@@ -188,23 +220,6 @@ class Router {
$directory = Bundle::path($bundle).'controllers/'; $directory = Bundle::path($bundle).'controllers/';
// We need to determine in which directory to look for the controllers.
// If the first segment of the request corresponds to a bundle that
// is installed for the application, we will use that bundle's
// controller path, otherwise we'll use the application's.
if (Bundle::routable($segments[0]))
{
$bundle = $segments[0];
// We shift the bundle name off of the URI segments because it will not
// be used to find a controller within the bundle. If we were to leave
// it in the segments, every bundle controller would need to be nested
// within a sub-directory matching the bundle name.
array_shift($segments);
return static::controller($bundle, $method, $destination, $segments);
}
if ( ! is_null($key = static::controller_key($segments, $directory))) if ( ! is_null($key = static::controller_key($segments, $directory)))
{ {
// First, we'll extract the controller name, then, since we need // First, we'll extract the controller name, then, since we need
......
...@@ -256,6 +256,17 @@ class Str { ...@@ -256,6 +256,17 @@ class Str {
} }
/** /**
* Return the "URI" style segments in a given string.
*
* @param string $value
* @return array
*/
public static function segments($value)
{
return array_diff(explode('/', trim($value, '/')), array(''));
}
/**
* Generate a random alpha or alpha-numeric string. * Generate a random alpha or alpha-numeric string.
* *
* <code> * <code>
......
<?php
return array(
'dashboard' => array(
'location' => 'dashboard',
'handles' => 'dashboard',
),
);
\ No newline at end of file
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