Update to support version 3.3 of Kohana

This commit is contained in:
Sébastien Guibert 2013-02-22 17:36:24 +01:00
parent 714e3fa78d
commit c9506cd227
6 changed files with 232 additions and 119 deletions

View File

@ -1,8 +1,8 @@
# Kohana Multilang Module 2.0
# Kohana Multilang Module 3.0
!!! NEW VERSION 2.0 !!!
!!! NEW VERSION 3.0 !!!
Multilingual module for Kohana PHP Framework, version 3.1
Multilingual module for the Kohana PHP Framework, version 3.3
## Features
@ -59,7 +59,7 @@ Route::set('product.details', 'products/<product_id>-<product_slug>', array(
'product_id' => '[0-9]+',
'product_slug' => '.+',
))->defaults(array(
'controller' => 'product',
'controller' => 'Product',
'action' => 'details',
'product_id' => NULL,
'product_slug' => '',
@ -79,7 +79,7 @@ Let's take a look:
'product_id' => '[0-9]+',
'product_slug' => '.+',
))->defaults(array(
'controller' => 'product',
'controller' => 'Product',
'action' => 'details',
'product_id' => NULL,
'product_slug' => '',
@ -91,7 +91,7 @@ If you wanna create a route for only one language, you're gonna have to pass a 4
Route::set('product.made-in-france', 'produits/fabrique-en-france', NULL, 'fr')
->defaults(array(
'controller' => 'product',
'controller' => 'Product',
'action' => 'made_in_france',
));

View File

@ -18,11 +18,13 @@ class Multilang_Core {
*/
static public function find_user_language()
{
if(Kohana::config('multilang.auto_detect'))
$config = Kohana::$config->load('multilang');
if($config->auto_detect)
{
// Get the list of supported languages
$languages = (array) Kohana::config('multilang.languages');
$cookie = Kohana::config('multilang.cookie');
$languages = $config->languages;
$cookie = $config->cookie;
// Look for language cookie first
if($lang = Cookie::get($cookie))
@ -48,7 +50,7 @@ class Multilang_Core {
}
}
// Return the hard-coded default language as final fallback
return Kohana::config('multilang.default');
return $config->default;
}
/**
@ -56,8 +58,10 @@ class Multilang_Core {
*/
static public function init()
{
$config = Kohana::$config->load('multilang');
// Get the list of supported languages
$langs = (array) Kohana::config('multilang.languages');
$langs = $config->languages;
// Set the language in I18n
I18n::lang($langs[Request::$lang]['i18n']);
@ -65,7 +69,7 @@ class Multilang_Core {
// Set locale
setlocale(LC_ALL, $langs[Request::$lang]['locale']);
$cookie = Kohana::config('multilang.cookie');
$cookie = $config->cookie;
// Update language cookie if needed
if(Cookie::get($cookie) !== Request::$lang)
{
@ -80,7 +84,9 @@ class Multilang_Core {
*/
static public function selector($current = TRUE)
{
$languages = (array) Kohana::config('multilang.languages');
$config = Kohana::$config->load('multilang');
$languages = $config->languages;
// Get the current route name
$current_route = Route::name(Request::initial()->route());
@ -120,7 +126,7 @@ class Multilang_Core {
// We juste need to change the language parameter
$route = Request::initial()->route();
$params['lang'] = NULL;
if(!Kohana::config('multilang.hide_default') || Kohana::config('multilang.default') !== $lang)
if(!$config->hide_default || $config->default !== $lang)
{
$params['lang'] = $lang;
}

View File

@ -11,6 +11,7 @@ class Multilang_Request extends Kohana_Request {
*/
static public $lang = NULL;
/**
*
* Extension of the request factory method. If none given, the URI will
@ -20,65 +21,51 @@ class Multilang_Request extends Kohana_Request {
* If the URI does contain a language segment, I18n and locale will be set and
* a cookie with the current language aswell.
*
* @param string URI of the request
* @param Kohana_Cache cache object
* @param array $injected_routes an array of routes to use, for testing
* @param string $uri URI of the request
* @param array $client_params An array of params to pass to the request client
* @param bool $allow_external Allow external requests? (deprecated in 3.3)
* @param array $injected_routes An array of routes to use, for testing
* @return void|Request
* @throws Request_Exception
* @uses Route::all
* @uses Route::matches
* @return Request
*/
public static function factory($uri = TRUE, Cache $cache = NULL, $injected_routes = array())
public static function factory($uri = TRUE, $client_params = array(), $allow_external = TRUE, $injected_routes = array())
{
$config = Kohana::$config->load('multilang');
if(!Kohana::$is_cli)
// If we don't hide the default language, we must look for a language code for the root uri
if(Request::detect_uri() === '' AND $config->auto_detect AND $uri === TRUE)
{
// If we don't hide the default language, we must look for a language code for the root uri
if(Request::detect_uri() === '' && Kohana::config('multilang.auto_detect') && $uri === TRUE)
$lang = Multilang::find_user_language();
if(!$config->hide_default OR $lang != $config->default)
{
$lang = Multilang::find_user_language();
if(!Kohana::config('multilang.hide_default') || $lang != Kohana::config('multilang.default'))
{
// Use the default server protocol
$protocol = (isset($_SERVER['SERVER_PROTOCOL'])) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1';
// Use the default server protocol
$protocol = (isset($_SERVER['SERVER_PROTOCOL'])) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1';
// Redirect to the root URI, but with language prepended
header($protocol.' 302 Found');
header('Location: '.URL::base(TRUE, TRUE).$lang.'/');
exit;
}
// Redirect to the root URI, but with language prepended
header($protocol.' 302 Found');
header('Location: '.URL::base(TRUE, TRUE).$lang.'/');
exit;
}
}
$request = parent::factory($uri, $cache, $injected_routes);
// If the default language is hidden or there is no language, we manually set it to default
if(Kohana::config('multilang.hide_default') && $request->param('lang') === NULL || $request->route()->lang === NULL)
{
Request::$lang = Kohana::config('multilang.default');
}
else
{
Request::$lang = $request->param('lang');
}
Multilang::init();
return $request;
return parent::factory($uri, $client_params, $allow_external, $injected_routes);
}
/**
* ONLY REMOVE THE FRONT SLASHES FROM THE URI
* We don't want to remove the trailing slash from the uri
*/
public function __construct($uri, Cache $cache = NULL, $injected_routes = array())
public function __construct($uri, $client_params = array(), $allow_external = TRUE, $injected_routes = array())
{
// Remove the front slashes
$uri = ltrim($uri, '/');
$client_params = is_array($client_params) ? $client_params : array();
// Initialise the header
$this->_header = new HTTP_Header(array());
// Assign injected routes
$this->_injected_routes = $injected_routes;
$this->_routes = $injected_routes;
// Cleanse query parameters from URI (faster that parse_url())
$split_uri = explode('?', $uri);
@ -94,58 +81,16 @@ class Multilang_Request extends Kohana_Request {
}
// Detect protocol (if present)
// Always default to an internal request if we don't have an initial.
// This prevents the default index.php from being able to proxy
// external pages.
if (Request::$initial === NULL OR strpos($uri, '://') === FALSE)
// $allow_external = FALSE prevents the default index.php from
// being able to proxy external pages.
if ( ! $allow_external OR strpos($uri, '://') === FALSE)
{
$processed_uri = Request::process_uri($uri, $this->_injected_routes);
if ($processed_uri === NULL)
{
throw new HTTP_Exception_404('Unable to find a route to match the URI: :uri', array(
':uri' => $uri,
));
}
// Store the URI
$this->_uri = $uri;
// Store the matching route
$this->_route = $processed_uri['route'];
$params = $processed_uri['params'];
// Is this route external?
$this->_external = $this->_route->is_external();
if (isset($params['directory']))
{
// Controllers are in a sub-directory
$this->_directory = $params['directory'];
}
// Store the controller
$this->_controller = $params['controller'];
if (isset($params['action']))
{
// Store the action
$this->_action = $params['action'];
}
else
{
// Use the default action
$this->_action = Route::$default_action;
}
// These are accessible as public vars and can be overloaded
unset($params['controller'], $params['action'], $params['directory']);
// Params cannot be changed once matched
$this->_params = $params;
// Remove trailing slashes from the URI (We don't want that)
//$this->_uri = trim($uri, '/');
$this->_uri = ltrim($uri, '/');
//$this->_route = new Route($uri);
// Apply the client
$this->_client = new Request_Client_Internal(array('cache' => $cache));
$this->_client = new Request_Client_Internal($client_params);
}
else
{
@ -155,13 +100,100 @@ class Multilang_Request extends Kohana_Request {
// Store the URI
$this->_uri = $uri;
// Set the security setting if required
if (strpos($uri, 'https://') === 0)
{
$this->secure(TRUE);
}
// Set external state
$this->_external = TRUE;
// Setup the client
$this->_client = new Request_Client_External(array('cache' => $cache));
$this->_client = Request_Client_External::factory($client_params);
}
}
/**
* Altered to detect the language in the uri
*
* @return Response
* @throws Request_Exception
* @throws HTTP_Exception_404
* @uses [Kohana::$profiling]
* @uses [Profiler]
*/
public function execute()
{
if ( ! $this->_external)
{
$processed = Request::process($this, $this->_routes);
if ($processed)
{
// Store the matching route
$this->_route = $processed['route'];
$params = $processed['params'];
// Is this route external?
$this->_external = $this->_route->is_external();
if (isset($params['directory']))
{
// Controllers are in a sub-directory
$this->_directory = $params['directory'];
}
// Store the controller
$this->_controller = $params['controller'];
// Store the action
$this->_action = (isset($params['action']))
? $params['action']
: Route::$default_action;
// These are accessible as public vars and can be overloaded
unset($params['controller'], $params['action'], $params['directory']);
// Params cannot be changed once matched
$this->_params = $params;
}
}
if ( ! $this->_route instanceof Route)
{
return HTTP_Exception::factory(404, 'Unable to find a route to match the URI: :uri', array(
':uri' => $this->_uri,
))->request($this)
->get_response();
}
if ( ! $this->_client instanceof Request_Client)
{
throw new Request_Exception('Unable to execute :uri without a Kohana_Request_Client', array(
':uri' => $this->_uri,
));
}
// Multilang part
if(Request::$lang === NULL)
{
Request::$lang = $this->_route->lang;
}
$config = Kohana::$config->load('multilang');
if($config->hide_default AND $this->param('lang') === NULL OR $this->_route->lang === NULL AND $this->param('lang') === NULL)
{
Request::$lang = $config->default;
}
else
{
Request::$lang = $this->param('lang');
}
Multilang::init();
return $this->_client->execute($this);
}
}

View File

@ -18,7 +18,9 @@ class Multilang_Route extends Kohana_Route {
*/
static public function set($name, $uri_callback = NULL, $regex = NULL, $lang = NULL)
{
if(!Kohana::config('multilang.hide_default') || Kohana::config('multilang.default') != $lang)
$config = Kohana::$config->load('multilang');
if(!$config->hide_default || $config->default != $lang)
{
if($lang !== NULL)
{
@ -59,8 +61,8 @@ class Multilang_Route extends Kohana_Route {
$name = $lang.'.'.$name;
} // then the default language
elseif(isset(Route::$_routes[Kohana::config('multilang.default').'.'.$name])) {
$name = Kohana::config('multilang.default').'.'.$name;
elseif(isset(Route::$_routes[Kohana::$config->load('multilang')->default.'.'.$name])) {
$name = $config->default.'.'.$name;
}
// And if we don't have any for this language, it means that route is neither defined nor multilingual
return parent::get($name);
@ -162,5 +164,73 @@ class Multilang_Route extends Kohana_Route {
return URL::site(Route::get($name, $lang)->uri($params), $protocol);
}
/**
* We don't want to remove the trailing slash.
*/
public function matches(Request $request)
{
// Get the URI from the Request
//$uri = trim($request->uri(), '/');
$uri = ltrim($request->uri(), '/');
if ( ! preg_match($this->_route_regex, $uri, $matches))
return FALSE;
$params = array();
foreach ($matches as $key => $value)
{
if (is_int($key))
{
// Skip all unnamed keys
continue;
}
// Set the value for all matched keys
$params[$key] = $value;
}
foreach ($this->_defaults as $key => $value)
{
if ( ! isset($params[$key]) OR $params[$key] === '')
{
// Set default values for any key that was not matched
$params[$key] = $value;
}
}
if ( ! empty($params['controller']))
{
// PSR-0: Replace underscores with spaces, run ucwords, then replace underscore
$params['controller'] = str_replace(' ', '_', ucwords(str_replace('_', ' ', $params['controller'])));
}
if ( ! empty($params['directory']))
{
// PSR-0: Replace underscores with spaces, run ucwords, then replace underscore
$params['directory'] = str_replace(' ', '_', ucwords(str_replace('_', ' ', $params['directory'])));
}
if ($this->_filters)
{
foreach ($this->_filters as $callback)
{
// Execute the filter giving it the route, params, and request
$return = call_user_func($callback, $this, $params, $request);
if ($return === FALSE)
{
// Filter has aborted the match
return FALSE;
}
elseif (is_array($return))
{
// Filter has modified the parameters
$params = $return;
}
}
}
return $params;
}
}

View File

@ -26,13 +26,14 @@ class Multilang_Routes {
*/
static public function set($name, $uris = array(), $regex = NULL)
{
$config = Kohana::$config->load('multilang');
$routes = new Routes();
// We add the routes for each language and set their names to lang.name (en.homepage for example).
// The <lang> segment is also added on the uri if it's not hidden
$default_lang = Kohana::config('multilang.default');
$languages = Kohana::config('multilang.languages');
$default_lang = $config->default;
$languages = $config->languages;
// We first look for the default language uri which is obviously compulsory
$default_uri = Arr::get($uris, $default_lang);

View File

@ -7,14 +7,17 @@
* It is recommended to move this route into your bootstrap and adapt it.
*/
/*
$languages = array();
$lang_param = '<lang>/';
$config = Kohana::$config->load('multilang');
// Need a regex for all the available languages
foreach(Kohana::config('multilang.languages') as $lang => $settings)
foreach($config->languages as $lang => $settings)
{
// If we hdie the default language, we make lang parameter optional
if(Kohana::config('multilang.hide_default') && Kohana::config('multilang.default') === $lang)
if($config->.hide_default && $config->default === $lang)
{
$lang_param = '(<lang>/)';
}
@ -29,5 +32,6 @@ Route::set('default', $lang_param, array(
))->defaults(array(
'controller' => 'home',
'action' => 'index',
'lang' => Kohana::config('multilang.default'),
'lang' => $config->default,
));
*/