First Local Commit - After Clean up.
Signed-off-by: Rick Hays <rhays@haysgang.com>
This commit is contained in:
12
system/Router/Exceptions/RedirectException.php
Normal file
12
system/Router/Exceptions/RedirectException.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace CodeIgniter\Router\Exceptions;
|
||||
|
||||
/**
|
||||
* Redirect exception
|
||||
*/
|
||||
|
||||
class RedirectException extends \Exception
|
||||
{
|
||||
protected $code = 302;
|
||||
}
|
||||
17
system/Router/Exceptions/RouterException.php
Normal file
17
system/Router/Exceptions/RouterException.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php namespace CodeIgniter\Router\Exceptions;
|
||||
|
||||
use CodeIgniter\Exceptions\ExceptionInterface;
|
||||
use CodeIgniter\Exceptions\FrameworkException;
|
||||
|
||||
class RouterException extends FrameworkException implements ExceptionInterface
|
||||
{
|
||||
public static function forInvalidParameterType()
|
||||
{
|
||||
return new static(lang('Router.invalidParameterType'));
|
||||
}
|
||||
|
||||
public static function forMissingDefaultRoute()
|
||||
{
|
||||
return new static(lang('Router.missingDefaultRoute'));
|
||||
}
|
||||
}
|
||||
1570
system/Router/RouteCollection.php
Normal file
1570
system/Router/RouteCollection.php
Normal file
File diff suppressed because it is too large
Load Diff
276
system/Router/RouteCollectionInterface.php
Normal file
276
system/Router/RouteCollectionInterface.php
Normal file
@@ -0,0 +1,276 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* CodeIgniter
|
||||
*
|
||||
* An open source application development framework for PHP
|
||||
*
|
||||
* This content is released under the MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2019 British Columbia Institute of Technology
|
||||
* Copyright (c) 2019 CodeIgniter Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @package CodeIgniter
|
||||
* @author CodeIgniter Dev Team
|
||||
* @copyright 2019 CodeIgniter Foundation
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
* @link https://codeigniter.com
|
||||
* @since Version 4.0.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Router;
|
||||
|
||||
/**
|
||||
* Interface RouteCollectionInterface
|
||||
*
|
||||
* A Route Collection's sole job is to hold a series of routes. The required
|
||||
* number of methods is kept very small on purpose, but implementors may
|
||||
* add a number of additional methods to customize how the routes are defined.
|
||||
*
|
||||
* The RouteCollection provides the Router with the routes so that it can determine
|
||||
* which controller should be ran.
|
||||
*
|
||||
* @package CodeIgniter\Router
|
||||
*/
|
||||
interface RouteCollectionInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Adds a single route to the collection.
|
||||
*
|
||||
* @param string $from
|
||||
* @param array|string $to
|
||||
* @param array $options
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function add(string $from, $to, array $options = null);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Registers a new constraint with the system. Constraints are used
|
||||
* by the routes as placeholders for regular expressions to make defining
|
||||
* the routes more human-friendly.
|
||||
*
|
||||
* You can pass an associative array as $placeholder, and have
|
||||
* multiple placeholders added at once.
|
||||
*
|
||||
* @param string|array $placeholder
|
||||
* @param string $pattern
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function addPlaceholder($placeholder, string $pattern = null);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Sets the default namespace to use for Controllers when no other
|
||||
* namespace has been specified.
|
||||
*
|
||||
* @param $value
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function setDefaultNamespace(string $value);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Sets the default controller to use when no other controller has been
|
||||
* specified.
|
||||
*
|
||||
* @param $value
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function setDefaultController(string $value);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Sets the default method to call on the controller when no other
|
||||
* method has been set in the route.
|
||||
*
|
||||
* @param $value
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function setDefaultMethod(string $value);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Tells the system whether to convert dashes in URI strings into
|
||||
* underscores. In some search engines, including Google, dashes
|
||||
* create more meaning and make it easier for the search engine to
|
||||
* find words and meaning in the URI for better SEO. But it
|
||||
* doesn't work well with PHP method names....
|
||||
*
|
||||
* @param boolean $value
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function setTranslateURIDashes(bool $value);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* If TRUE, the system will attempt to match the URI against
|
||||
* Controllers by matching each segment against folders/files
|
||||
* in APPPATH/Controllers, when a match wasn't found against
|
||||
* defined routes.
|
||||
*
|
||||
* If FALSE, will stop searching and do NO automatic routing.
|
||||
*
|
||||
* @param boolean $value
|
||||
*
|
||||
* @return RouteCollectionInterface
|
||||
*/
|
||||
public function setAutoRoute(bool $value): self;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Sets the class/method that should be called if routing doesn't
|
||||
* find a match. It can be either a closure or the controller/method
|
||||
* name exactly like a route is defined: Users::index
|
||||
*
|
||||
* This setting is passed to the Router class and handled there.
|
||||
*
|
||||
* @param callable|null $callable
|
||||
*
|
||||
* @return RouteCollectionInterface
|
||||
*/
|
||||
public function set404Override($callable = null): self;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the 404 Override setting, which can be null, a closure
|
||||
* or the controller/string.
|
||||
*
|
||||
* @return string|\Closure|null
|
||||
*/
|
||||
public function get404Override();
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the name of the default controller. With Namespace.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultController();
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the name of the default method to use within the controller.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultMethod();
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the current value of the translateURIDashes setting.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function shouldTranslateURIDashes();
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the flag that tells whether to autoRoute URI against Controllers.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function shouldAutoRoute();
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the raw array of available routes.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getRoutes();
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the current HTTP Verb being used.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getHTTPVerb();
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Attempts to look up a route based on it's destination.
|
||||
*
|
||||
* If a route exists:
|
||||
*
|
||||
* 'path/(:any)/(:any)' => 'Controller::method/$1/$2'
|
||||
*
|
||||
* This method allows you to know the Controller and method
|
||||
* and get the route that leads to it.
|
||||
*
|
||||
* // Equals 'path/$param1/$param2'
|
||||
* reverseRoute('Controller::method', $param1, $param2);
|
||||
*
|
||||
* @param string $search
|
||||
* @param array ...$params
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function reverseRoute(string $search, ...$params);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Determines if the route is a redirecting route.
|
||||
*
|
||||
* @param string $from
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isRedirect(string $from): bool;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Grabs the HTTP status code from a redirecting Route.
|
||||
*
|
||||
* @param string $from
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getRedirectCode(string $from): int;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
}
|
||||
691
system/Router/Router.php
Normal file
691
system/Router/Router.php
Normal file
@@ -0,0 +1,691 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* CodeIgniter
|
||||
*
|
||||
* An open source application development framework for PHP
|
||||
*
|
||||
* This content is released under the MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2019 British Columbia Institute of Technology
|
||||
* Copyright (c) 2019 CodeIgniter Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @package CodeIgniter
|
||||
* @author CodeIgniter Dev Team
|
||||
* @copyright 2019 CodeIgniter Foundation
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
* @link https://codeigniter.com
|
||||
* @since Version 4.0.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Router;
|
||||
|
||||
use CodeIgniter\HTTP\Request;
|
||||
use CodeIgniter\Exceptions\PageNotFoundException;
|
||||
use CodeIgniter\Router\Exceptions\RedirectException;
|
||||
use CodeIgniter\Router\Exceptions\RouterException;
|
||||
|
||||
/**
|
||||
* Request router.
|
||||
*/
|
||||
class Router implements RouterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* A RouteCollection instance.
|
||||
*
|
||||
* @var RouteCollection
|
||||
*/
|
||||
protected $collection;
|
||||
|
||||
/**
|
||||
* Sub-directory that contains the requested controller class.
|
||||
* Primarily used by 'autoRoute'.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $directory;
|
||||
|
||||
/**
|
||||
* The name of the controller class.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $controller;
|
||||
|
||||
/**
|
||||
* The name of the method to use.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $method;
|
||||
|
||||
/**
|
||||
* An array of binds that were collected
|
||||
* so they can be sent to closure routes.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $params = [];
|
||||
|
||||
/**
|
||||
* The name of the front controller.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $indexPage = 'index.php';
|
||||
|
||||
/**
|
||||
* Whether dashes in URI's should be converted
|
||||
* to underscores when determining method names.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $translateURIDashes = false;
|
||||
|
||||
/**
|
||||
* The route that was matched for this request.
|
||||
*
|
||||
* @var array|null
|
||||
*/
|
||||
protected $matchedRoute = null;
|
||||
|
||||
/**
|
||||
* The options set for the matched route.
|
||||
*
|
||||
* @var array|null
|
||||
*/
|
||||
protected $matchedRouteOptions = null;
|
||||
|
||||
/**
|
||||
* The locale that was detected in a route.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $detectedLocale = null;
|
||||
|
||||
/**
|
||||
* The filter info from Route Collection
|
||||
* if the matched route should be filtered.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $filterInfo;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Stores a reference to the RouteCollection object.
|
||||
*
|
||||
* @param RouteCollectionInterface $routes
|
||||
* @param Request $request
|
||||
*/
|
||||
public function __construct(RouteCollectionInterface $routes, Request $request = null)
|
||||
{
|
||||
$this->collection = $routes;
|
||||
|
||||
$this->controller = $this->collection->getDefaultController();
|
||||
$this->method = $this->collection->getDefaultMethod();
|
||||
|
||||
$this->collection->setHTTPVerb($request->getMethod() ?? strtolower($_SERVER['REQUEST_METHOD']));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @param string|null $uri
|
||||
*
|
||||
* @return mixed|string
|
||||
* @throws \CodeIgniter\Router\Exceptions\RedirectException
|
||||
* @throws \CodeIgniter\Exceptions\PageNotFoundException
|
||||
*/
|
||||
public function handle(string $uri = null)
|
||||
{
|
||||
$this->translateURIDashes = $this->collection->shouldTranslateURIDashes();
|
||||
|
||||
// If we cannot find a URI to match against, then
|
||||
// everything runs off of it's default settings.
|
||||
if (empty($uri))
|
||||
{
|
||||
return strpos($this->controller, '\\') === false
|
||||
? $this->collection->getDefaultNamespace() . $this->controller
|
||||
: $this->controller;
|
||||
}
|
||||
|
||||
if ($this->checkRoutes($uri))
|
||||
{
|
||||
if ($this->collection->isFiltered($this->matchedRoute[0]))
|
||||
{
|
||||
$this->filterInfo = $this->collection->getFilterForRoute($this->matchedRoute[0]);
|
||||
}
|
||||
|
||||
return $this->controller;
|
||||
}
|
||||
|
||||
// Still here? Then we can try to match the URI against
|
||||
// Controllers/directories, but the application may not
|
||||
// want this, like in the case of API's.
|
||||
if (! $this->collection->shouldAutoRoute())
|
||||
{
|
||||
throw new PageNotFoundException("Can't find a route for '{$uri}'.");
|
||||
}
|
||||
|
||||
$this->autoRoute($uri);
|
||||
|
||||
return $this->controllerName();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the filter info for the matched route, if any.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFilter()
|
||||
{
|
||||
return $this->filterInfo;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the name of the matched controller.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function controllerName()
|
||||
{
|
||||
return $this->translateURIDashes
|
||||
? str_replace('-', '_', $this->controller)
|
||||
: $this->controller;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the name of the method to run in the
|
||||
* chosen container.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function methodName(): string
|
||||
{
|
||||
return $this->translateURIDashes
|
||||
? str_replace('-', '_', $this->method)
|
||||
: $this->method;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the 404 Override settings from the Collection.
|
||||
* If the override is a string, will split to controller/index array.
|
||||
*/
|
||||
public function get404Override()
|
||||
{
|
||||
$route = $this->collection->get404Override();
|
||||
|
||||
if (is_string($route))
|
||||
{
|
||||
$routeArray = explode('::', $route);
|
||||
|
||||
return [
|
||||
$routeArray[0], // Controller
|
||||
$routeArray[1] ?? 'index', // Method
|
||||
];
|
||||
}
|
||||
|
||||
if (is_callable($route))
|
||||
{
|
||||
return $route;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the binds that have been matched and collected
|
||||
* during the parsing process as an array, ready to send to
|
||||
* instance->method(...$params).
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function params(): array
|
||||
{
|
||||
return $this->params;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the name of the sub-directory the controller is in,
|
||||
* if any. Relative to APPPATH.'Controllers'.
|
||||
*
|
||||
* Only used when auto-routing is turned on.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function directory(): string
|
||||
{
|
||||
return ! empty($this->directory) ? $this->directory : '';
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the routing information that was matched for this
|
||||
* request, if a route was defined.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public function getMatchedRoute()
|
||||
{
|
||||
return $this->matchedRoute;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns all options set for the matched route
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public function getMatchedRouteOptions()
|
||||
{
|
||||
return $this->matchedRouteOptions;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Sets the value that should be used to match the index.php file. Defaults
|
||||
* to index.php but this allows you to modify it in case your are using
|
||||
* something like mod_rewrite to remove the page. This allows you to set
|
||||
* it a blank.
|
||||
*
|
||||
* @param $page
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function setIndexPage($page): self
|
||||
{
|
||||
$this->indexPage = $page;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Tells the system whether we should translate URI dashes or not
|
||||
* in the URI from a dash to an underscore.
|
||||
*
|
||||
* @param boolean|false $val
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setTranslateURIDashes(bool $val = false): self
|
||||
{
|
||||
$this->translateURIDashes = $val;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns true/false based on whether the current route contained
|
||||
* a {locale} placeholder.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasLocale()
|
||||
{
|
||||
return (bool) $this->detectedLocale;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the detected locale, if any, or null.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLocale()
|
||||
{
|
||||
return $this->detectedLocale;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Compares the uri string against the routes that the
|
||||
* RouteCollection class defined for us, attempting to find a match.
|
||||
* This method will modify $this->controller, etal as needed.
|
||||
*
|
||||
* @param string $uri The URI path to compare against the routes
|
||||
*
|
||||
* @return boolean Whether the route was matched or not.
|
||||
* @throws \CodeIgniter\Router\Exceptions\RedirectException
|
||||
*/
|
||||
protected function checkRoutes(string $uri): bool
|
||||
{
|
||||
$routes = $this->collection->getRoutes($this->collection->getHTTPVerb());
|
||||
|
||||
$uri = $uri === '/'
|
||||
? $uri
|
||||
: ltrim($uri, '/ ');
|
||||
|
||||
// Don't waste any time
|
||||
if (empty($routes))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Loop through the route array looking for wildcards
|
||||
foreach ($routes as $key => $val)
|
||||
{
|
||||
$key = $key === '/'
|
||||
? $key
|
||||
: ltrim($key, '/ ');
|
||||
|
||||
// Are we dealing with a locale?
|
||||
if (strpos($key, '{locale}') !== false)
|
||||
{
|
||||
$localeSegment = array_search('{locale}', preg_split('/[\/]*((^[a-zA-Z0-9])|\(([^()]*)\))*[\/]+/m', $key));
|
||||
|
||||
// Replace it with a regex so it
|
||||
// will actually match.
|
||||
$key = str_replace('{locale}', '[^/]+', $key);
|
||||
}
|
||||
|
||||
// Does the RegEx match?
|
||||
if (preg_match('#^' . $key . '$#', $uri, $matches))
|
||||
{
|
||||
// Store our locale so CodeIgniter object can
|
||||
// assign it to the Request.
|
||||
if (isset($localeSegment))
|
||||
{
|
||||
// The following may be inefficient, but doesn't upset NetBeans :-/
|
||||
$temp = (explode('/', $uri));
|
||||
$this->detectedLocale = $temp[$localeSegment];
|
||||
unset($localeSegment);
|
||||
}
|
||||
|
||||
// Are we using Closures? If so, then we need
|
||||
// to collect the params into an array
|
||||
// so it can be passed to the controller method later.
|
||||
if (! is_string($val) && is_callable($val))
|
||||
{
|
||||
$this->controller = $val;
|
||||
|
||||
// Remove the original string from the matches array
|
||||
array_shift($matches);
|
||||
|
||||
$this->params = $matches;
|
||||
|
||||
$this->matchedRoute = [
|
||||
$key,
|
||||
$val,
|
||||
];
|
||||
|
||||
$this->matchedRouteOptions = $this->collection->getRoutesOptions($key);
|
||||
|
||||
return true;
|
||||
}
|
||||
// Are we using the default method for back-references?
|
||||
|
||||
// Support resource route when function with subdirectory
|
||||
// ex: $routes->resource('Admin/Admins');
|
||||
if (strpos($val, '$') !== false && strpos($key, '(') !== false && strpos($key, '/') !== false)
|
||||
{
|
||||
$replacekey = str_replace('/(.*)', '', $key);
|
||||
$val = preg_replace('#^' . $key . '$#', $val, $uri);
|
||||
$val = str_replace($replacekey, str_replace('/', '\\', $replacekey), $val);
|
||||
}
|
||||
elseif (strpos($val, '$') !== false && strpos($key, '(') !== false)
|
||||
{
|
||||
$val = preg_replace('#^' . $key . '$#', $val, $uri);
|
||||
}
|
||||
elseif (strpos($val, '/') !== false)
|
||||
{
|
||||
[
|
||||
$controller,
|
||||
$method,
|
||||
] = explode( '::', $val );
|
||||
|
||||
// Only replace slashes in the controller, not in the method.
|
||||
$controller = str_replace('/', '\\', $controller);
|
||||
|
||||
$val = $controller . '::' . $method;
|
||||
}
|
||||
|
||||
// Is this route supposed to redirect to another?
|
||||
if ($this->collection->isRedirect($key))
|
||||
{
|
||||
throw new RedirectException($val, $this->collection->getRedirectCode($key));
|
||||
}
|
||||
|
||||
$this->setRequest(explode('/', $val));
|
||||
|
||||
$this->matchedRoute = [
|
||||
$key,
|
||||
$val,
|
||||
];
|
||||
|
||||
$this->matchedRouteOptions = $this->collection->getRoutesOptions($key);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Attempts to match a URI path against Controllers and directories
|
||||
* found in APPPATH/Controllers, to find a matching route.
|
||||
*
|
||||
* @param string $uri
|
||||
*/
|
||||
public function autoRoute(string $uri)
|
||||
{
|
||||
$segments = explode('/', $uri);
|
||||
|
||||
$segments = $this->validateRequest($segments);
|
||||
|
||||
// If we don't have any segments left - try the default controller;
|
||||
// WARNING: Directories get shifted out of the segments array.
|
||||
if (empty($segments))
|
||||
{
|
||||
$this->setDefaultController();
|
||||
}
|
||||
// If not empty, then the first segment should be the controller
|
||||
else
|
||||
{
|
||||
$this->controller = ucfirst(array_shift($segments));
|
||||
}
|
||||
|
||||
// Use the method name if it exists.
|
||||
// If it doesn't, no biggie - the default method name
|
||||
// has already been set.
|
||||
if (! empty($segments))
|
||||
{
|
||||
$this->method = array_shift($segments);
|
||||
}
|
||||
|
||||
if (! empty($segments))
|
||||
{
|
||||
$this->params = $segments;
|
||||
}
|
||||
|
||||
// Load the file so that it's available for CodeIgniter.
|
||||
$file = APPPATH . 'Controllers/' . $this->directory . $this->controllerName() . '.php';
|
||||
if (is_file($file))
|
||||
{
|
||||
include_once $file;
|
||||
}
|
||||
|
||||
// Ensure the controller stores the fully-qualified class name
|
||||
// We have to check for a length over 1, since by default it will be '\'
|
||||
if (strpos($this->controller, '\\') === false && strlen($this->collection->getDefaultNamespace()) > 1)
|
||||
{
|
||||
$this->controller = str_replace('/', '\\', $this->collection->getDefaultNamespace() . $this->directory . $this->controllerName());
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Attempts to validate the URI request and determine the controller path.
|
||||
*
|
||||
* @param array $segments URI segments
|
||||
*
|
||||
* @return array URI segments
|
||||
*/
|
||||
protected function validateRequest(array $segments): array
|
||||
{
|
||||
$segments = array_filter($segments, function ($segment) {
|
||||
return ! empty($segment) || ($segment !== '0' || $segment !== 0);
|
||||
});
|
||||
$segments = array_values($segments);
|
||||
|
||||
$c = count($segments);
|
||||
$directory_override = isset($this->directory);
|
||||
|
||||
// Loop through our segments and return as soon as a controller
|
||||
// is found or when such a directory doesn't exist
|
||||
while ($c-- > 0)
|
||||
{
|
||||
$test = $this->directory . ucfirst($this->translateURIDashes === true ? str_replace('-', '_', $segments[0]) : $segments[0]);
|
||||
|
||||
if (! is_file(APPPATH . 'Controllers/' . $test . '.php') && $directory_override === false && is_dir(APPPATH . 'Controllers/' . $this->directory . ucfirst($segments[0])))
|
||||
{
|
||||
$this->setDirectory(array_shift($segments), true);
|
||||
continue;
|
||||
}
|
||||
|
||||
return $segments;
|
||||
}
|
||||
|
||||
// This means that all segments were actually directories
|
||||
return $segments;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Sets the sub-directory that the controller is in.
|
||||
*
|
||||
* @param string|null $dir
|
||||
* @param boolean|false $append
|
||||
*/
|
||||
protected function setDirectory(string $dir = null, bool $append = false)
|
||||
{
|
||||
if (empty($dir))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$dir = ucfirst($dir);
|
||||
|
||||
if ($append !== true || empty($this->directory))
|
||||
{
|
||||
$this->directory = str_replace('.', '', trim($dir, '/')) . '/';
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->directory .= str_replace('.', '', trim($dir, '/')) . '/';
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set request route
|
||||
*
|
||||
* Takes an array of URI segments as input and sets the class/method
|
||||
* to be called.
|
||||
*
|
||||
* @param array $segments URI segments
|
||||
*/
|
||||
protected function setRequest(array $segments = [])
|
||||
{
|
||||
// If we don't have any segments - try the default controller;
|
||||
if (empty($segments))
|
||||
{
|
||||
$this->setDefaultController();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
list($controller, $method) = array_pad(explode('::', $segments[0]), 2, null);
|
||||
|
||||
$this->controller = $controller;
|
||||
|
||||
// $this->method already contains the default method name,
|
||||
// so don't overwrite it with emptiness.
|
||||
if (! empty($method))
|
||||
{
|
||||
$this->method = $method;
|
||||
}
|
||||
|
||||
array_shift($segments);
|
||||
|
||||
$this->params = $segments;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Sets the default controller based on the info set in the RouteCollection.
|
||||
*/
|
||||
protected function setDefaultController()
|
||||
{
|
||||
if (empty($this->controller))
|
||||
{
|
||||
throw RouterException::forMissingDefaultRoute();
|
||||
}
|
||||
|
||||
// Is the method being specified?
|
||||
if (sscanf($this->controller, '%[^/]/%s', $class, $this->method) !== 2)
|
||||
{
|
||||
$this->method = 'index';
|
||||
}
|
||||
|
||||
if (! is_file(APPPATH . 'Controllers/' . $this->directory . ucfirst($class) . '.php'))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$this->controller = ucfirst($class);
|
||||
|
||||
log_message('info', 'Used the default controller.');
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
}
|
||||
115
system/Router/RouterInterface.php
Normal file
115
system/Router/RouterInterface.php
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* CodeIgniter
|
||||
*
|
||||
* An open source application development framework for PHP
|
||||
*
|
||||
* This content is released under the MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2019 British Columbia Institute of Technology
|
||||
* Copyright (c) 2019 CodeIgniter Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @package CodeIgniter
|
||||
* @author CodeIgniter Dev Team
|
||||
* @copyright 2019 CodeIgniter Foundation
|
||||
* @license https://opensource.org/licenses/MIT MIT License
|
||||
* @link https://codeigniter.com
|
||||
* @since Version 4.0.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace CodeIgniter\Router;
|
||||
|
||||
use CodeIgniter\HTTP\Request;
|
||||
|
||||
/**
|
||||
* Expected behavior of a Router.
|
||||
*/
|
||||
interface RouterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Stores a reference to the RouteCollection object.
|
||||
*
|
||||
* @param RouteCollectionInterface $routes
|
||||
* @param \CodeIgniter\HTTP\Request $request
|
||||
*/
|
||||
public function __construct(RouteCollectionInterface $routes, Request $request = null);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Scans the URI and attempts to match the current URI to the
|
||||
* one of the defined routes in the RouteCollection.
|
||||
*
|
||||
* @param string $uri
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(string $uri = null);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the name of the matched controller.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function controllerName();
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the name of the method to run in the
|
||||
* chosen container.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function methodName();
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the binds that have been matched and collected
|
||||
* during the parsing process as an array, ready to send to
|
||||
* instance->method(...$params).
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function params();
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Sets the value that should be used to match the index.php file. Defaults
|
||||
* to index.php but this allows you to modify it in case your are using
|
||||
* something like mod_rewrite to remove the page. This allows you to set
|
||||
* it a blank.
|
||||
*
|
||||
* @param $page
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function setIndexPage($page);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
}
|
||||
Reference in New Issue
Block a user