diff --git a/application/config/application.php b/application/config/application.php index 74ae6984..644dd4b6 100644 --- a/application/config/application.php +++ b/application/config/application.php @@ -115,6 +115,7 @@ return array( 'Arr' => 'Laravel\\Arr', 'Asset' => 'Laravel\\Asset', 'Auth' => 'Laravel\\Auth', + 'Autoloader' => 'Laravel\\Autoloader', 'Benchmark' => 'Laravel\\Benchmark', 'Cache' => 'Laravel\\Cache\\Manager', 'Config' => 'Laravel\\Config', diff --git a/laravel/auth.php b/laravel/auth.php index 16d1cd40..f660e5cd 100644 --- a/laravel/auth.php +++ b/laravel/auth.php @@ -74,9 +74,13 @@ class Auth { // If the user was not found in the database, but a "remember me" cookie // exists, we will attempt to recall the user based on the cookie value. - if (is_null(static::$user) and ! is_null($cookie = Cookie::get(Auth::remember_key))) + // Since all cookies contain a fingerprint hash verifying that the have + // not been modified on the client, we should be able to trust it. + $recaller = Cookie::get(Auth::remember_key); + + if (is_null(static::$user) and ! is_null($recaller)) { - static::$user = static::recall($cookie); + static::$user = static::recall($recaller); } return static::$user; @@ -89,14 +93,14 @@ class Auth { * set by Laravel include a fingerprint hash to ensure the cookie * value is not changed on the client. * - * @param string $cookie + * @param string $recaller * @return mixed */ - protected static function recall($cookie) + protected static function recall($recaller) { - $cookie = explode('|', Crypter::decrypt($cookie)); + $recaller = explode('|', Crypter::decrypt($recaller)); - if ( ! is_null($user = call_user_func(Config::get('auth.user'), $cookie[0]))) + if ( ! is_null($user = call_user_func(Config::get('auth.user'), $recaller[0]))) { static::login($user); @@ -174,7 +178,7 @@ class Auth { */ protected static function remember($id) { - $cookie = Crypter::encrypt($id.'|'.Str::random(40)); + $recaller = Crypter::encrypt($id.'|'.Str::random(40)); // This method assumes the "remember me" cookie should have the same // configuration as the session cookie. Since this cookie, like the @@ -184,7 +188,7 @@ class Auth { extract($config, EXTR_SKIP); - Cookie::forever(Auth::remember_key, $cookie, $path, $domain, $secure); + Cookie::forever(Auth::remember_key, $recaller, $path, $domain, $secure); } /** diff --git a/laravel/autoloader.php b/laravel/autoloader.php index 1cbbf4e1..7b574537 100644 --- a/laravel/autoloader.php +++ b/laravel/autoloader.php @@ -3,37 +3,30 @@ class Autoloader { /** - * The PSR-0 compliant libraries registered with the auto-loader. + * The mappings from class names to file paths. * * @var array */ - protected static $libraries = array(); + public static $mappings = array(); /** * The paths to be searched by the auto-loader. * * @var array */ - protected static $paths = array(BASE_PATH, MODEL_PATH, LIBRARY_PATH); + protected static $paths = array(MODEL_PATH, LIBRARY_PATH); /** * Load the file corresponding to a given class. * - * Laravel loads classes out of three directories: the core "laravel" directory, - * and the application "models" and "libraries" directories. All of the file - * names are lower cased and the directory structure corresponds with the - * class namespaces. - * - * The application "libraries" directory also supports the inclusion of PSR-0 - * compliant libraries. These libraries will be detected automatically and - * will be loaded according to the PSR-0 naming conventions. + * This method is registerd in the core bootstrap file as an SPL Autoloader. * * @param string $class * @return void */ public static function load($class) { - if (array_key_exists($class, Config::$items['application']['aliases'])) + if (isset(Config::$items['application']['aliases'][$class])) { return class_alias(Config::$items['application']['aliases'][$class], $class); } @@ -52,27 +45,26 @@ class Autoloader { */ protected static function find($class) { - // After PHP namespaces were introduced, most libaries ditched underscores for - // namespaces to indicate the class directory hierarchy. We will check for the - // presence of namespace slashes to determine the directory separator. - $separator = (strpos($class, '\\') !== false) ? '\\' : '_'; + // First we will look for the class in the hard-coded class mappings, since + // this is the fastest way to resolve a class name to its associated file. + // This saves us from having to search through the file system manually. + if (isset(static::$mappings[$class])) + { + return static::$mappings[$class]; + } - $library = substr($class, 0, strpos($class, $separator)); - - $file = str_replace('\\', '/', $class); - - // If the namespace has been registered as a PSR-0 compliant library, we will + // If the library has been registered as a PSR-0 compliant library, we will // load the library according to the PSR-0 naming standards, which state that // namespaces and underscores indicate the directory hierarchy of the class. - if (isset(static::$libraries[$library])) + if (isset(static::$libraries[static::library($class)])) { - return LIBRARY_PATH.str_replace('_', '/', $file).EXT; + return LIBRARY_PATH.str_replace(array('\\', '_'), '/', $class).EXT; } // Next we will search through the common Laravel paths for the class file. - // The Laravel framework path, along with the libraries and models paths - // will be searched according to the Laravel class naming standard. - $lower = strtolower($file); + // The Laravel libraries and models directories will be searched according + // to the Laravel class naming standards. + $file = strtolower(str_replace('\\', '/', $class)); foreach (static::$paths as $path) { @@ -82,29 +74,105 @@ class Autoloader { } } - // If we could not find the class file in any of the auto-loaded locations - // according to the Laravel naming standard, we will search the libraries - // directory for the class according to the PSR-0 naming standard. - if (file_exists($path = LIBRARY_PATH.str_replace('_', '/', $file).EXT)) - { - static::$libraries[] = $library; - - return $path; - } - // Since not all controllers will be resolved by the controller resolver, // we will do a quick check in the controller directory for the class. // For instance, since base controllers would not be resolved by the // controller class, we will need to resolve them here. - if (strpos($class, '_Controller') !== false) + if (file_exists($path = static::controller($class))) { - $controller = str_replace(array('_Controller', '_'), array('', '/'), $class); - - if (file_exists($path = strtolower(CONTROLLER_PATH.$controller.EXT))) - { - return $path; - } + return $path; } } + /** + * Extract the "library" name from the given class. + * + * The library name is essentially the namespace, or the string that preceeds + * the first PSR-0 separator. PSR-0 states that namespaces or undescores may + * be used to indicate the directory structure in which the file resides. + * + * @param string $class + * @return string + */ + protected static function library($class) + { + if (($separator = strpos($class, '\\')) !== false) + { + return substr($class, 0, $separator); + } + elseif (($separator = strpos($class, '_')) !== false) + { + return substr($class, 0, $separator); + } + } + + /** + * Translate a given controller class name into the corresponding file name. + * + * The controller suffix will be removed, and the underscores will be translated + * into directory slashes. Of course, the entire class name will be converted to + * lower case as well. + * + * + * // Returns "user/profile"... + * $file = static::controller('User_Profile_Controller'); + * + * + * @param string $class + * @return string + */ + protected static function controller($class) + { + $controller = str_replace(array('_', '_Controller'), array('/', ''), $class); + + return CONTROLLER_PATH.strtolower($controller).EXT; + } + + /** + * Register an array of class to path mappings. + * + * The mappings will be used to resolve file paths from class names when + * a class is lazy loaded through the Autoloader, providing a faster way + * of resolving file paths than the typical file_exists method. + * + * + * // Register a class mapping with the Autoloader + * Autoloader::maps(array('User' => MODEL_PATH.'user'.EXT)); + * + * + * @param array $mappings + * @return void + */ + public static function maps($mappings) + { + foreach ($mappings as $class => $path) + { + static::$mappings[$class] = $path; + } + } + + /** + * Register PSR-0 libraries with the Autoloader. + * + * The library names given to this method should match directories within + * the application libraries directory. This method provides an easy way + * to indicate that some libraries should be loaded using the PSR-0 + * naming conventions instead of the Laravel conventions. + * + * + * // Register the "Assetic" library with the Autoloader + * Autoloader::libraries('Assetic'); + * + * // Register several libraries with the Autoloader + * Autoloader::libraries(array('Assetic', 'Twig')); + * + * + * @param array $libraries + * @return void + */ + public static function libraries($libraries) + { + static::$libraries = array_merge(static::$libraries, (array) $libraries); + } + } \ No newline at end of file diff --git a/laravel/bootstrap/core.php b/laravel/bootstrap/core.php deleted file mode 100644 index cb5201a2..00000000 --- a/laravel/bootstrap/core.php +++ /dev/null @@ -1,73 +0,0 @@ - SYS_PATH.'arr'.EXT, + 'Laravel\\Asset' => SYS_PATH.'asset'.EXT, + 'Laravel\\Auth' => SYS_PATH.'auth'.EXT, + 'Laravel\\Benchmark' => SYS_PATH.'benchmark'.EXT, + 'Laravel\\Blade' => SYS_PATH.'blade'.EXT, + 'Laravel\\Config' => SYS_PATH.'config'.EXT, + 'Laravel\\Cookie' => SYS_PATH.'cookie'.EXT, + 'Laravel\\Crypter' => SYS_PATH.'crypter'.EXT, + 'Laravel\\File' => SYS_PATH.'file'.EXT, + 'Laravel\\Form' => SYS_PATH.'form'.EXT, + 'Laravel\\Hash' => SYS_PATH.'hash'.EXT, + 'Laravel\\HTML' => SYS_PATH.'html'.EXT, + 'Laravel\\Inflector' => SYS_PATH.'inflector'.EXT, + 'Laravel\\Input' => SYS_PATH.'input'.EXT, + 'Laravel\\IoC' => SYS_PATH.'ioc'.EXT, + 'Laravel\\Lang' => SYS_PATH.'lang'.EXT, + 'Laravel\\Memcached' => SYS_PATH.'memcached'.EXT, + 'Laravel\\Messages' => SYS_PATH.'messages'.EXT, + 'Laravel\\Paginator' => SYS_PATH.'paginator'.EXT, + 'Laravel\\Redirect' => SYS_PATH.'redirect'.EXT, + 'Laravel\\Redis' => SYS_PATH.'redis'.EXT, + 'Laravel\\Request' => SYS_PATH.'request'.EXT, + 'Laravel\\Response' => SYS_PATH.'response'.EXT, + 'Laravel\\Section' => SYS_PATH.'section'.EXT, + 'Laravel\\Str' => SYS_PATH.'str'.EXT, + 'Laravel\\URI' => SYS_PATH.'uri'.EXT, + 'Laravel\\URL' => SYS_PATH.'url'.EXT, + 'Laravel\\Validator' => SYS_PATH.'validator'.EXT, + 'Laravel\\View' => SYS_PATH.'view'.EXT, + 'Laravel\\Cache\\Manager' => SYS_PATH.'cache/manager'.EXT, + 'Laravel\\Cache\\Drivers\\APC' => SYS_PATH.'cache/drivers/apc'.EXT, + 'Laravel\\Cache\\Drivers\\Driver' => SYS_PATH.'cache/drivers/driver'.EXT, + 'Laravel\\Cache\\Drivers\\File' => SYS_PATH.'cache/drivers/file'.EXT, + 'Laravel\\Cache\\Drivers\\Memcached' => SYS_PATH.'cache/drivers/memcached'.EXT, + 'Laravel\\Cache\\Drivers\\Redis' => SYS_PATH.'cache/drivers/redis'.EXT, + 'Laravel\\Database\\Connection' => SYS_PATH.'database/connection'.EXT, + 'Laravel\\Database\\Expression' => SYS_PATH.'database/expression'.EXT, + 'Laravel\\Database\\Manager' => SYS_PATH.'database/manager'.EXT, + 'Laravel\\Database\\Query' => SYS_PATH.'database/query'.EXT, + 'Laravel\\Database\\Connectors\\Connector' => SYS_PATH.'database/connectors/connector'.EXT, + 'Laravel\\Database\\Connectors\\MySQL' => SYS_PATH.'database/connectors/mysql'.EXT, + 'Laravel\\Database\\Connectors\\Postgres' => SYS_PATH.'database/connectors/postgres'.EXT, + 'Laravel\\Database\\Connectors\\SQLite' => SYS_PATH.'database/connectors/sqlite'.EXT, + 'Laravel\\Database\\Eloquent\\Hydrator' => SYS_PATH.'database/eloquent/hydrator'.EXT, + 'Laravel\\Database\\Eloquent\\Model' => SYS_PATH.'database/eloquent/model'.EXT, + 'Laravel\\Database\\Grammars\\Grammar' => SYS_PATH.'database/grammars/grammar'.EXT, + 'Laravel\\Database\\Grammars\\MySQL' => SYS_PATH.'database/grammars/mysql'.EXT, + 'Laravel\\Routing\\Controller' => SYS_PATH.'routing/controller'.EXT, + 'Laravel\\Routing\\Filter' => SYS_PATH.'routing/filter'.EXT, + 'Laravel\\Routing\\Loader' => SYS_PATH.'routing/loader'.EXT, + 'Laravel\\Routing\\Route' => SYS_PATH.'routing/route'.EXT, + 'Laravel\\Routing\\Router' => SYS_PATH.'routing/router'.EXT, + 'Laravel\\Session\\Payload' => SYS_PATH.'session/payload'.EXT, + 'Laravel\\Session\\Drivers\\APC' => SYS_PATH.'session/drivers/apc'.EXT, + 'Laravel\\Session\\Drivers\\Cookie' => SYS_PATH.'session/drivers/cookie'.EXT, + 'Laravel\\Session\\Drivers\\Database' => SYS_PATH.'session/drivers/database'.EXT, + 'Laravel\\Session\\Drivers\\Driver' => SYS_PATH.'session/drivers/driver'.EXT, + 'Laravel\\Session\\Drivers\\Factory' => SYS_PATH.'session/drivers/factory'.EXT, + 'Laravel\\Session\\Drivers\\File' => SYS_PATH.'session/drivers/file'.EXT, + 'Laravel\\Session\\Drivers\\Memcached' => SYS_PATH.'session/drivers/memcached'.EXT, + 'Laravel\\Session\\Drivers\\Redis' => SYS_PATH.'session/drivers/redis'.EXT, + 'Laravel\\Session\\Drivers\\Sweeper' => SYS_PATH.'session/drivers/sweeper'.EXT, +); + +/** + * Define a few global, convenient functions. These functions + * provide short-cuts for things like the retrieval of language + * lines and HTML::entities. They just make our lives as devs a + * little sweeter and more enjoyable. + */ +require SYS_PATH.'helpers'.EXT; \ No newline at end of file diff --git a/laravel/input.php b/laravel/input.php index d475bd90..9c723fde 100644 --- a/laravel/input.php +++ b/laravel/input.php @@ -68,29 +68,19 @@ class Input { * * @return void */ - public static function flash() + public static function flash($filter = null, $items = array()) { - if (Config::$items['session']['driver'] !== '') - { - IoC::core('session')->flash(Input::old_input, static::get()); - } + IoC::core('session')->flash(Input::old_input, static::get()); } /** * Flush the old input from the session. * - * On a successful form submission, the application may redirect to another form. - * If this is the case, it may be necessary to flush the old input so that the new - * form does not have the previous form's data. - * * @return void */ public static function flush() { - if (Config::$items['session']['driver'] !== '') - { - IoC::core('session')->flash(Input::old_input, array()); - } + IoC::core('session')->flash(Input::old_input, array()); } /** @@ -101,7 +91,7 @@ class Input { */ public static function had($key) { - return ( ! is_null(static::old($key)) and trim((string) static::old($key)) !== ''); + return trim((string) static::old($key)) !== ''; } /** @@ -121,11 +111,6 @@ class Input { */ public static function old($key = null, $default = null) { - if (Config::get('session.driver') == '') - { - throw new \UnexpectedValueException('A session driver must be specified to access old input.'); - } - $old = IoC::core('session')->get(Input::old_input, array()); return Arr::get($old, $key, $default); diff --git a/laravel/lang.php b/laravel/lang.php index 217338e3..01238f3c 100644 --- a/laravel/lang.php +++ b/laravel/lang.php @@ -26,19 +26,12 @@ class Lang { /** * All of the loaded language lines. * - * The array is keyed by [$language.$file]. + * The array is keyed by [$language][$file]. * * @var array */ protected static $lines = array(); - /** - * The paths containing the language files. - * - * @var array - */ - protected static $paths = array(LANG_PATH); - /** * Create a new Lang instance. * @@ -109,7 +102,7 @@ class Lang { return ($default instanceof Closure) ? call_user_func($default) : $default; } - return $this->replace(Arr::get(static::$lines[$this->language.$file], $line, $default)); + return $this->replace(Arr::get(static::$lines[$this->language][$file], $line, $default)); } /** @@ -155,29 +148,31 @@ class Lang { /** * Load all of the language lines from a language file. * + * If the language file is successfully loaded, true will be returned. + * * @param string $file * @return bool */ protected function load($file) { - if (isset(static::$lines[$this->language.$file])) return true; + if (isset(static::$lines[$this->language][$file])) return true; $language = array(); - foreach (static::$paths as $directory) + if (file_exists($path = LANG_PATH.$this->language.'/'.$file.EXT)) { - if (file_exists($path = $directory.$this->language.'/'.$file.EXT)) - { - $language = array_merge($language, require $path); - } + $language = array_merge($language, require $path); } // If language lines were actually found, they will be loaded into // the array containing all of the lines for all languages and files. // The array is keyed by the language and the file name. - if (count($language) > 0) static::$lines[$this->language.$file] = $language; + if (count($language) > 0) + { + static::$lines[$this->language][$file] = $language; + } - return isset(static::$lines[$this->language.$file]); + return isset(static::$lines[$this->language][$file]); } /** diff --git a/laravel/laravel.php b/laravel/laravel.php index 09f2ad7e..b7957786 100644 --- a/laravel/laravel.php +++ b/laravel/laravel.php @@ -5,7 +5,7 @@ * configuration class, and the class auto-loader. Once this file * has run, the framework is essentially ready for use. */ -require 'bootstrap/core.php'; +require 'core.php'; /** * Register the default timezone for the application. This will be @@ -123,11 +123,6 @@ ini_set('display_errors', 'Off'); */ if (Config::$items['session']['driver'] !== '') { - require SYS_PATH.'ioc'.EXT; - require SYS_PATH.'session/payload'.EXT; - require SYS_PATH.'session/drivers/driver'.EXT; - require SYS_PATH.'session/drivers/factory'.EXT; - $driver = Session\Drivers\Factory::make(Config::$items['session']['driver']); $session = new Session\Payload($driver); @@ -137,20 +132,6 @@ if (Config::$items['session']['driver'] !== '') IoC::instance('laravel.session', $session); } -/** - * Manually load some core classes that are used on every request so - * we can avoid using the loader for these classes. This saves us - * some overhead on each request. - */ -require SYS_PATH.'uri'.EXT; -require SYS_PATH.'input'.EXT; -require SYS_PATH.'request'.EXT; -require SYS_PATH.'response'.EXT; -require SYS_PATH.'routing/route'.EXT; -require SYS_PATH.'routing/router'.EXT; -require SYS_PATH.'routing/loader'.EXT; -require SYS_PATH.'routing/filter'.EXT; - /** * Gather the input to the application based on the current request. * The input will be gathered based on the current request method and diff --git a/laravel/messages.php b/laravel/messages.php index 1f40859b..a2c1a0ce 100644 --- a/laravel/messages.php +++ b/laravel/messages.php @@ -24,6 +24,11 @@ class Messages { /** * Add a message to the collector. * + * + * // Add a message for the e-mail attribute + * $messages->add('email', 'The e-mail address is invalid.'); + * + * * @param string $key * @param string $message * @return void @@ -42,7 +47,7 @@ class Messages { */ protected function unique($key, $message) { - return ! isset($this->messages[$key]) or array_search($message, $this->messages[$key]) === false; + return ! isset($this->messages[$key]) or ! in_array($message, $this->messages[$key]); } /** @@ -91,10 +96,8 @@ class Messages { * @param string $format * @return array */ - public function get($key = null, $format = ':message') + public function get($key, $format = ':message') { - if (is_null($key)) return $this->all($format); - if (array_key_exists($key, $this->messages)) { return $this->format($this->messages[$key], $format); diff --git a/laravel/redirect.php b/laravel/redirect.php index 2d13aa1e..ad65b005 100644 --- a/laravel/redirect.php +++ b/laravel/redirect.php @@ -64,6 +64,34 @@ class Redirect extends Response { return $this; } + /** + * Flash the old input to the session and return the Redirect instance. + * + * This method has the same signature as the Input::flash method, it just provides + * a convenient method of flashing the input and return the Redirect in one line. + * Once the input has been flashed, it can be retrieved via the Input::old method. + * + * + * // Redirect and flash all of the input data to the session + * return Redirect::to_login()->with_input(); + * + * // Redirect and flash only a few of the input items + * return Redirect::to_login()->with_input('only', array('email', 'username')); + * + * // Redirect and flash all but a few of the input items + * return Redirect::to_login()->with_input('except', array('password', 'ssn')); + * + * + * @param string $filter + * @param array $items + * @return Redirect + */ + public function with_input($filter = null, $items = array()) + { + Input::flash($filter, $items); + return $this; + } + /** * Magic Method to handle creation of redirects to named routes. * @@ -73,22 +101,28 @@ class Redirect extends Response { * * // Create a redirect response to a named route using HTTPS * return Redirect::to_secure_profile(); + * + * // Create a redirect response to a named route with wildcard parameters + * return Redirect::to_profile(array($username)); * */ public static function __callStatic($method, $parameters) { + // Extract the parameters that should be placed in the URL. These parameters + // are used to fill all of the wildcard slots in the route URI definition. + // They are passed as the first parameter to this magic method. + $wildcards = (isset($parameters[0])) ? $parameters[0] : array(); + $status = (isset($parameters[1])) ? $parameters[1] : 302; - - $parameters = (isset($parameters[0])) ? $parameters[0] : array(); if (strpos($method, 'to_secure_') === 0) { - return static::to(URL::to_route(substr($method, 10), $parameters, true), $status); + return static::to(URL::to_route(substr($method, 10), $wildcards, true), $status); } if (strpos($method, 'to_') === 0) { - return static::to(URL::to_route(substr($method, 3), $parameters), $status); + return static::to(URL::to_route(substr($method, 3), $wildcards), $status); } throw new \BadMethodCallException("Method [$method] is not defined on the Redirect class."); diff --git a/laravel/response.php b/laravel/response.php index 0bcaf1d0..55a51495 100644 --- a/laravel/response.php +++ b/laravel/response.php @@ -235,7 +235,7 @@ class Response { */ public function send() { - if ( ! headers_sent()) $this->headers(); + if ( ! headers_sent()) $this->send_headers(); echo $this->render(); } @@ -254,7 +254,7 @@ class Response { * * @return void */ - public function headers() + public function send_headers() { if ( ! isset($this->headers['Content-Type'])) { diff --git a/laravel/routing/controller.php b/laravel/routing/controller.php index b028c61f..ebb91faf 100644 --- a/laravel/routing/controller.php +++ b/laravel/routing/controller.php @@ -15,6 +15,13 @@ abstract class Controller { */ public $layout; + /** + * Indicates if the controller uses RESTful routing. + * + * @var bool + */ + public $restful = false; + /** * The filters assigned to the controller. * @@ -125,7 +132,19 @@ abstract class Controller { if (is_null($response)) { - $response = call_user_func_array(array($this, "action_{$method}"), $parameters); + // The developer may mark the controller as being "RESTful" which + // indicates that the controller actions are prefixed with the + // HTTP verb they respond to rather than the word "action". + if ($this->restful) + { + $action = strtolower(Request::method()).'_'.$method; + } + else + { + $action = "action_{$method}"; + } + + $response = call_user_func_array(array($this, $action), $parameters); // If the controller has specified a layout view. The response // returned by the controller method will be bound to that view diff --git a/laravel/routing/filter.php b/laravel/routing/filter.php index 3be1072c..2bde4e22 100644 --- a/laravel/routing/filter.php +++ b/laravel/routing/filter.php @@ -160,7 +160,7 @@ class Filter_Collection { * $this->filter('before', 'auth')->except('index'); * * // Specify a filter for all methods except "index" and "home" - * $this->filter('before', 'auth')->except(array('index', 'home')); + * $this->filter('before', 'auth')->except('index', 'home'); * * * @param array $methods @@ -168,7 +168,7 @@ class Filter_Collection { */ public function except($methods) { - $this->except = (array) $methods; + $this->except = (count(func_get_args()) > 1) ? func_get_args() : (array) $methods; return $this; } @@ -184,7 +184,7 @@ class Filter_Collection { * $this->filter('before', 'auth')->only('index'); * * // Specify a filter for only the "index" and "home" methods - * $this->filter('before', 'auth')->only(array('index', 'home')); + * $this->filter('before', 'auth')->only('index', 'home'); * * * @param array $methods @@ -192,7 +192,7 @@ class Filter_Collection { */ public function only($methods) { - $this->only = (array) $methods; + $this->only = (count(func_get_args()) > 1) ? func_get_args() : (array) $methods; return $this; } @@ -208,7 +208,7 @@ class Filter_Collection { * $this->filter('before', 'csrf')->on('post'); * * // Specify that a filter applies for multiple HTTP request methods - * $this->filter('before', 'csrf')->on(array('post', 'put')); + * $this->filter('before', 'csrf')->on('post', 'put'); * * * @param array $methods @@ -216,7 +216,13 @@ class Filter_Collection { */ public function on($methods) { - $this->methods = array_map('strtolower', (array) $methods); + $methos = (count(func_get_args()) > 1) ? func_get_args() : (array) $methods; + + foreach ($methods as $method) + { + $this->methods[] = strtolower($method); + } + return $this; }