Commit 8dfb50c8 authored by Taylor Otwell's avatar 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 {
*
* @var array
*/
protected static $bundles;
public static $bundles = array();
/**
* A cache of the parsed bundle elements.
*
* @var array
*/
protected static $elements = array();
public static $elements = array();
/**
* All of the bundles that have been started.
*
* @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.
......@@ -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
* @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 {
*/
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 {
}
/**
* 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
*/
public static function all()
{
if (is_array(static::$bundles)) return 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;
return array_keys(static::$bundles);
}
}
\ No newline at end of file
......@@ -138,4 +138,18 @@ Autoloader::$mappings = array(
* having to worry about the namespacing. The developer is also
* free to remove aliases when they extend core classes.
*/
Autoloader::$aliases = Config::get('application.aliases');
\ No newline at end of file
Autoloader::$aliases = Config::get('application.aliases');
/**
* 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
......@@ -131,16 +131,6 @@ unset($input[Request::spoofer]);
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
* not typically considered a bundle, it is started like one and
......@@ -149,13 +139,11 @@ foreach (Config::get('application.bundles') as $bundle)
Bundle::start(DEFAULT_BUNDLE);
/**
* If the first segment of the URI corresponds with a bundle we'll
* start that bundle. By convention, bundles handle all URIs which
* begin with their bundle name.
* 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.
*/
$bundle = URI::segment(1);
if ( ! is_null($bundle) and Bundle::routable($bundle))
foreach (Config::get('application.bundles') as $bundle)
{
Bundle::start($bundle);
}
......
<?php namespace Laravel\Routing; use Closure, Laravel\Bundle;
<?php namespace Laravel\Routing; use Closure, Laravel\Str, Laravel\Bundle;
class Router {
......@@ -128,6 +128,12 @@ class Router {
*/
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
// slash before the URI. We'll put the request method and URI in
// that format so we can easily check for literal matches.
......@@ -139,10 +145,44 @@ class Router {
}
// If we can't find a literal match, we'll iterate through all of
// the registered routes attempting to find a matching route that
// uses wildcards or regular expressions.
// the registered routes to find a matching route that uses some
// 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)
{
// 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)
{
$pattern = '#^'.static::wildcards($route).'$#';
......@@ -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 {
// use the default method, which is "index".
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');
......@@ -188,23 +220,6 @@ class Router {
$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)))
{
// First, we'll extract the controller name, then, since we need
......
......@@ -255,6 +255,17 @@ class Str {
return str_replace(' ', '_', static::title(str_replace($search, ' ', $value)));
}
/**
* 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.
*
......
<?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