From c9506cd227917f7b9456e88945ad14c2426f2a57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Guibert?= Date: Fri, 22 Feb 2013 17:36:24 +0100 Subject: [PATCH] Update to support version 3.3 of Kohana --- README.md | 12 +- classes/multilang/core.php | 24 ++-- classes/multilang/request.php | 222 +++++++++++++++++++--------------- classes/multilang/route.php | 76 +++++++++++- classes/multilang/routes.php | 5 +- init.php | 12 +- 6 files changed, 232 insertions(+), 119 deletions(-) diff --git a/README.md b/README.md index 2a2202f..689ce18 100644 --- a/README.md +++ b/README.md @@ -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/-', 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', )); diff --git a/classes/multilang/core.php b/classes/multilang/core.php index bdf1260..451c880 100644 --- a/classes/multilang/core.php +++ b/classes/multilang/core.php @@ -17,12 +17,14 @@ class Multilang_Core { * @return string language key, e.g. "en", "fr", "nl", "en_US", "en-us", etc. */ 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; } diff --git a/classes/multilang/request.php b/classes/multilang/request.php index f31b3b0..b85f29c 100644 --- a/classes/multilang/request.php +++ b/classes/multilang/request.php @@ -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()) { - - 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() === '' && Kohana::config('multilang.auto_detect') && $uri === TRUE) - { - $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'; + $config = Kohana::$config->load('multilang'); - // 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) + // 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) { - Request::$lang = Kohana::config('multilang.default'); - } - else - { - Request::$lang = $request->param('lang'); - } + $lang = Multilang::find_user_language(); + if(!$config->hide_default OR $lang != $config->default) + { + // Use the default server protocol + $protocol = (isset($_SERVER['SERVER_PROTOCOL'])) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1'; - Multilang::init(); - return $request; + // Redirect to the root URI, but with language prepended + header($protocol.' 302 Found'); + header('Location: '.URL::base(TRUE, TRUE).$lang.'/'); + exit; + } + } + + 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); + } } \ No newline at end of file diff --git a/classes/multilang/route.php b/classes/multilang/route.php index 61b5573..3aa3f33 100644 --- a/classes/multilang/route.php +++ b/classes/multilang/route.php @@ -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; + } } \ No newline at end of file diff --git a/classes/multilang/routes.php b/classes/multilang/routes.php index 4efd384..4be4498 100644 --- a/classes/multilang/routes.php +++ b/classes/multilang/routes.php @@ -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 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); diff --git a/init.php b/init.php index 6ca9764..1dd5f25 100644 --- a/init.php +++ b/init.php @@ -7,14 +7,17 @@ * It is recommended to move this route into your bootstrap and adapt it. */ +/* $languages = array(); $lang_param = '/'; +$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 = '(/)'; } @@ -29,5 +32,6 @@ Route::set('default', $lang_param, array( ))->defaults(array( 'controller' => 'home', 'action' => 'index', - 'lang' => Kohana::config('multilang.default'), -)); \ No newline at end of file + 'lang' => $config->default, +)); + */ \ No newline at end of file