diff --git a/classes/kohana/arr.php b/classes/kohana/arr.php index 9df715ee6..945247114 100644 --- a/classes/kohana/arr.php +++ b/classes/kohana/arr.php @@ -441,7 +441,15 @@ public static function merge(array $a1, array $a2) else { // Find the values that are not already present - $diff = array_diff($val, $result[$key]); + $diff = array(); + + foreach ($val as $val_val) + { + if ( ! in_array($val_val, $result[$key], TRUE)) + { + $diff[] = $val_val; + } + } // Indexed arrays are merged to prevent duplicates $result[$key] = array_merge($result[$key], $diff); diff --git a/classes/kohana/config/group.php b/classes/kohana/config/group.php index 3adfbba69..f6e00ac66 100644 --- a/classes/kohana/config/group.php +++ b/classes/kohana/config/group.php @@ -12,7 +12,7 @@ * @category Configuration * @author Kohana Team * @copyright (c) 2012 Kohana Team - * @license http://kohanaphp.com/license + * @license http://kohanaframework.org/license */ class Kohana_Config_Group extends ArrayObject { diff --git a/classes/kohana/config/reader.php b/classes/kohana/config/reader.php index 9750cb8a0..46aeb8a50 100644 --- a/classes/kohana/config/reader.php +++ b/classes/kohana/config/reader.php @@ -13,7 +13,7 @@ interface Kohana_Config_Reader extends Kohana_Config_Source { /** - * Tries to load the specificed configuration group + * Tries to load the specified configuration group * * Returns FALSE if group does not exist or an array if it does * diff --git a/classes/kohana/config/source.php b/classes/kohana/config/source.php index fcc57f3e3..1ed18a58f 100644 --- a/classes/kohana/config/source.php +++ b/classes/kohana/config/source.php @@ -8,7 +8,7 @@ * @category Configuration * @author Kohana Team * @copyright (c) 2012 Kohana Team - * @license http://kohanaphp.com/license + * @license http://kohanaframework.org/license */ interface Kohana_Config_Source {} diff --git a/classes/kohana/config/writer.php b/classes/kohana/config/writer.php index ea2b19ab8..cc7ae5291 100644 --- a/classes/kohana/config/writer.php +++ b/classes/kohana/config/writer.php @@ -8,7 +8,7 @@ * @package Kohana * @author Kohana Team * @copyright (c) 2008-2012 Kohana Team - * @license http://kohanaphp.com/license + * @license http://kohanaframework.org/license */ interface Kohana_Config_Writer extends Kohana_Config_Source { diff --git a/classes/kohana/cookie.php b/classes/kohana/cookie.php index 5260a35ea..99887d6bf 100644 --- a/classes/kohana/cookie.php +++ b/classes/kohana/cookie.php @@ -124,7 +124,6 @@ public static function set($name, $value, $expiration = NULL) * * @param string $name cookie name * @return boolean - * @uses Cookie::set */ public static function delete($name) { diff --git a/classes/kohana/core.php b/classes/kohana/core.php index 4d34a78a3..08328501e 100644 --- a/classes/kohana/core.php +++ b/classes/kohana/core.php @@ -327,7 +327,7 @@ public static function init(array $settings = NULL) } // Determine if the extremely evil magic quotes are enabled - Kohana::$magic_quotes = version_compare(PHP_VERSION, '5.4') < 0 AND get_magic_quotes_gpc(); + Kohana::$magic_quotes = (version_compare(PHP_VERSION, '5.4') < 0 AND get_magic_quotes_gpc()); // Sanitize all request variables $_GET = Kohana::sanitize($_GET); @@ -388,7 +388,7 @@ public static function deinit() /** * Reverts the effects of the `register_globals` PHP setting by unsetting - * all global varibles except for the default super globals (GPCS, etc), + * all global variables except for the default super globals (GPCS, etc), * which is a [potential security hole.][ref-wikibooks] * * This is called automatically by [Kohana::init] if `register_globals` is @@ -898,7 +898,7 @@ public static function cache($name, $data = NULL, $lifetime = NULL) } /** - * Get a message from a file. Messages are arbitary strings that are stored + * Get a message from a file. Messages are arbitrary strings that are stored * in the `messages/` directory and reference by a key. Translation is not * performed on the returned values. See [message files](kohana/files/messages) * for more information. @@ -967,18 +967,37 @@ public static function error_handler($code, $error, $file = NULL, $line = NULL) /** * Catches errors that are not caught by the error handler, such as E_PARSE. + * + * In case of an exception, the Kohana exception handler registers + * this shutdown_handler again. We'll count the number of visits to + * this function using a local static function variable, and exit(1) + * on the second visit. + * @see issue #3931 * - * @uses Kohana_Exception::handler * @return void */ public static function shutdown_handler() { + // test if we have already shutdown, if TRUE, exit(1) + static $shutdown_handler_visited = FALSE; + if ($shutdown_handler_visited) + { + exit(1); + } + $shutdown_handler_visited = TRUE; + if ( ! Kohana::$_init) { // Do not execute when not active return; } + // Retrieve the current exception handler + $handler = set_exception_handler(array('Kohana_Exception', 'handler')); + + // Restore it back to it's previous state + restore_exception_handler(); + try { if (Kohana::$caching === TRUE AND Kohana::$_files_changed === TRUE) @@ -990,7 +1009,7 @@ public static function shutdown_handler() catch (Exception $e) { // Pass the exception to the handler - Kohana_Exception::handler($e); + call_user_func($handler, $e); } if (Kohana::$errors AND $error = error_get_last() AND in_array($error['type'], Kohana::$shutdown_errors)) @@ -999,7 +1018,7 @@ public static function shutdown_handler() ob_get_level() and ob_clean(); // Fake an exception for nice debugging - Kohana_Exception::handler(new ErrorException($error['message'], $error['type'], 0, $error['file'], $error['line'])); + call_user_func($handler, new ErrorException($error['message'], $error['type'], 0, $error['file'], $error['line'])); // Shutdown now to avoid a "death loop" exit(1); diff --git a/classes/kohana/debug.php b/classes/kohana/debug.php index 435387d67..fd8d795b0 100644 --- a/classes/kohana/debug.php +++ b/classes/kohana/debug.php @@ -6,7 +6,7 @@ * @category Base * @author Kohana Team * @copyright (c) 2008-2012 Kohana Team - * @license http://kohanaphp.com/license + * @license http://kohanaframework.org/license */ class Kohana_Debug { diff --git a/classes/kohana/file.php b/classes/kohana/file.php index c7f10c0cb..2368c0eb3 100644 --- a/classes/kohana/file.php +++ b/classes/kohana/file.php @@ -163,16 +163,16 @@ public static function split($filename, $piece_size = 10) // Write files in 8k blocks $block_size = 1024 * 8; - // Total number of peices - $peices = 0; + // Total number of pieces + $pieces = 0; while ( ! feof($file)) { // Create another piece - $peices += 1; + $pieces += 1; // Create a new file piece - $piece = str_pad($peices, 3, '0', STR_PAD_LEFT); + $piece = str_pad($pieces, 3, '0', STR_PAD_LEFT); $piece = fopen($filename.'.'.$piece, 'wb+'); // Number of bytes read @@ -195,7 +195,7 @@ public static function split($filename, $piece_size = 10) // Close the file fclose($file); - return $peices; + return $pieces; } /** @@ -214,7 +214,7 @@ public static function join($filename) // Read files in 8k blocks $block_size = 1024 * 8; - // Total number of peices + // Total number of pieces $pieces = 0; while (is_file($piece = $filename.'.'.str_pad($pieces + 1, 3, '0', STR_PAD_LEFT))) @@ -231,7 +231,7 @@ public static function join($filename) fwrite($file, fread($piece, $block_size)); } - // Close the peice + // Close the piece fclose($piece); } diff --git a/classes/kohana/form.php b/classes/kohana/form.php index e9d1a455c..3e6109d91 100644 --- a/classes/kohana/form.php +++ b/classes/kohana/form.php @@ -2,7 +2,7 @@ /** * Form helper class. Unless otherwise noted, all generated HTML will be made * safe using the [HTML::chars] method. This prevents against simple XSS - * attacks that could otherwise be trigged by inserting HTML characters into + * attacks that could otherwise be triggered by inserting HTML characters into * form fields. * * @package Kohana @@ -28,7 +28,7 @@ class Kohana_Form { * @param mixed $action form action, defaults to the current request URI, or [Request] class to use * @param array $attributes html attributes * @return string - * @uses Request::instance + * @uses Request * @uses URL::site * @uses HTML::attributes */ diff --git a/classes/kohana/http.php b/classes/kohana/http.php index 066464d1a..b254fd074 100644 --- a/classes/kohana/http.php +++ b/classes/kohana/http.php @@ -12,7 +12,7 @@ * @author Kohana Team * @since 3.1.0 * @copyright (c) 2008-2012 Kohana Team - * @license http://kohanaphp.com/license + * @license http://kohanaframework.org/license */ abstract class Kohana_HTTP { diff --git a/classes/kohana/http/cache.php b/classes/kohana/http/cache.php index f6546536c..b38bfc550 100644 --- a/classes/kohana/http/cache.php +++ b/classes/kohana/http/cache.php @@ -1,6 +1,6 @@ getCode(); @@ -146,7 +152,7 @@ public static function handler(Exception $e) // Just display the text of the exception echo "\n{$error}\n"; - exit(1); + return TRUE; } if ( ! headers_sent()) @@ -162,7 +168,7 @@ public static function handler(Exception $e) // Just display the text of the exception echo "\n{$error}\n"; - exit(1); + return TRUE; } // Start an output buffer @@ -183,7 +189,7 @@ public static function handler(Exception $e) // Display the contents of the output buffer echo ob_get_clean(); - exit(1); + return TRUE; } catch (Exception $e) { @@ -193,8 +199,8 @@ public static function handler(Exception $e) // Display the exception text echo Kohana_Exception::text($e), "\n"; - // Exit with an error status - exit(1); + // return + return TRUE; } } diff --git a/classes/kohana/log/stderr.php b/classes/kohana/log/stderr.php index 715ce902d..b15947bc1 100644 --- a/classes/kohana/log/stderr.php +++ b/classes/kohana/log/stderr.php @@ -6,7 +6,7 @@ * @category Logging * @author Kohana Team * @copyright (c) 2008-2012 Kohana Team - * @license http://kohanaphp.com/license + * @license http://kohanaframework.org/license */ class Kohana_Log_StdErr extends Log_Writer { /** @@ -19,13 +19,10 @@ class Kohana_Log_StdErr extends Log_Writer { */ public function write(array $messages) { - // Set the log line format - $format = 'time --- type: body'; - foreach ($messages as $message) { // Writes out each message - fwrite(STDERR, PHP_EOL.strtr($format, $message)); + fwrite(STDERR, PHP_EOL.$message['time'].' --- '.$this->_log_levels[$message['level']].': '.$message['body']); } } } // End Kohana_Log_StdErr diff --git a/classes/kohana/log/stdout.php b/classes/kohana/log/stdout.php index 26c9668b5..2bdb67660 100644 --- a/classes/kohana/log/stdout.php +++ b/classes/kohana/log/stdout.php @@ -6,7 +6,7 @@ * @category Logging * @author Kohana Team * @copyright (c) 2008-2012 Kohana Team - * @license http://kohanaphp.com/license + * @license http://kohanaframework.org/license */ class Kohana_Log_StdOut extends Log_Writer { /** @@ -19,13 +19,10 @@ class Kohana_Log_StdOut extends Log_Writer { */ public function write(array $messages) { - // Set the log line format - $format = 'time --- type: body'; - foreach ($messages as $message) { // Writes out each message - fwrite(STDOUT, PHP_EOL.strtr($format, $message)); + fwrite(STDOUT, PHP_EOL.$message['time'].' --- '.$this->_log_levels[$message['level']].': '.$message['body']); } } } // End Kohana_Log_StdOut diff --git a/classes/kohana/profiler.php b/classes/kohana/profiler.php index e76ce3c43..f896b14c3 100644 --- a/classes/kohana/profiler.php +++ b/classes/kohana/profiler.php @@ -14,7 +14,7 @@ class Kohana_Profiler { /** - * @var integer maximium number of application stats to keep + * @var integer maximum number of application stats to keep */ public static $rollover = 1000; diff --git a/classes/kohana/request.php b/classes/kohana/request.php index c362076f5..bd1986717 100644 --- a/classes/kohana/request.php +++ b/classes/kohana/request.php @@ -38,7 +38,7 @@ class Kohana_Request implements HTTP_Request { /** * Creates a new request object for the given URI. New requests should be - * created using the [Request::instance] or [Request::factory] methods. + * created using the [Request::factory] method. * * $request = Request::factory($uri); * @@ -578,6 +578,12 @@ public static function process_uri($uri, $routes = NULL) foreach ($routes as $name => $route) { + // Use external routes for reverse routing only + if ($route->is_external()) + { + continue; + } + // We found something suitable if ($params = $route->matches($uri)) { @@ -752,7 +758,7 @@ protected static function _parse_accept( & $header, array $accepts = NULL) /** * Creates a new request object for the given URI. New requests should be - * created using the [Request::instance] or [Request::factory] methods. + * created using the [Request::factory] method. * * $request = new Request($uri); * @@ -899,7 +905,6 @@ public function uri() * * echo URL::site($this->request->uri(), $protocol); * - * @param array $params URI parameters * @param mixed $protocol protocol string or Request object * @return string * @since 3.0.7 @@ -907,10 +912,15 @@ public function uri() */ public function url($protocol = NULL) { - // Create a URI with the current route and convert it to a URL + if ($this->is_external()) + { + // If it's an external request return the URI + return $this->uri(); + } + + // Create a URI with the current route, convert to a URL and returns return URL::site($this->uri(), $protocol); } - /** * Retrieves a value from the route parameters. * diff --git a/classes/kohana/request/client/curl.php b/classes/kohana/request/client/curl.php index cb087d316..5a92b5ab4 100644 --- a/classes/kohana/request/client/curl.php +++ b/classes/kohana/request/client/curl.php @@ -1,7 +1,7 @@ body(); + // This will also add a Content-Type: application/x-www-form-urlencoded header unless you override it + if ($body = $request->body()) { + $options[CURLOPT_POSTFIELDS] = $body; + } // Process headers if ($headers = $request->headers()) @@ -111,7 +114,7 @@ public function _send_message(Request $request) /** * Sets the appropriate curl request options. Uses the responding options - * for POST and PUT, uses CURLOPT_CUSTOMREQUEST otherwise + * for POST, uses CURLOPT_CUSTOMREQUEST otherwise * @param Request $request * @param array $options * @return array @@ -122,9 +125,6 @@ public function _set_curl_request_method(Request $request, array $options) case Request::POST: $options[CURLOPT_POST] = TRUE; break; - case Request::PUT: - $options[CURLOPT_PUT] = TRUE; - break; default: $options[CURLOPT_CUSTOMREQUEST] = $request->method(); break; diff --git a/classes/kohana/request/client/http.php b/classes/kohana/request/client/http.php index 277648af0..76441a4c6 100644 --- a/classes/kohana/request/client/http.php +++ b/classes/kohana/request/client/http.php @@ -1,7 +1,7 @@ _uri; diff --git a/classes/kohana/session/native.php b/classes/kohana/session/native.php index 0858f2ab7..172d3b9e6 100644 --- a/classes/kohana/session/native.php +++ b/classes/kohana/session/native.php @@ -24,8 +24,31 @@ public function id() */ protected function _read($id = NULL) { + /** + * session_set_cookie_params will override php ini settings + * If Cookie::$domain is NULL or empty and is passed, PHP + * will override ini and sent cookies with the host name + * of the server which generated the cookie + * + * see issue #3604 + * + * see http://www.php.net/manual/en/function.session-set-cookie-params.php + * see http://www.php.net/manual/en/session.configuration.php#ini.session.cookie-domain + * + * set to Cookie::$domain if available, otherwise default to ini setting + */ + $session_cookie_domain = empty(Cookie::$domain) + ? ini_get('session.cookie_domain') + : Cookie::$domain; + // Sync up the session cookie with Cookie parameters - session_set_cookie_params($this->_lifetime, Cookie::$path, Cookie::$domain, Cookie::$secure, Cookie::$httponly); + session_set_cookie_params( + $this->_lifetime, + Cookie::$path, + $session_cookie_domain, + Cookie::$secure, + Cookie::$httponly + ); // Do not allow PHP to send Cache-Control headers session_cache_limiter(FALSE); diff --git a/classes/kohana/text.php b/classes/kohana/text.php index a0a1e2775..a9cc91f20 100644 --- a/classes/kohana/text.php +++ b/classes/kohana/text.php @@ -239,7 +239,7 @@ public static function random($type = NULL, $length = 8) * $str = Text::ucfirst('content-type'); // returns "Content-Type" * * @param string $string string to transform - * @param string $delimiter delemiter to use + * @param string $delimiter delimiter to use * @return string */ public static function ucfirst($string, $delimiter = '-') @@ -269,10 +269,13 @@ public static function reduce_slashes($str) * 'frick' => '#####', * )); * + * If argument $replacement is a single character, it will be used to replace + * the characters in the badword, otherwise it will replace the badword completely + * * @param string $str phrase to replace words in * @param array $badwords words to replace * @param string $replacement replacement string - * @param boolean $replace_partial_words replace words across word boundries (space, period, etc) + * @param boolean $replace_partial_words replace words across word boundaries (space, period, etc) * @return string * @uses UTF8::strlen */ @@ -293,12 +296,16 @@ public static function censor($str, $badwords, $replacement = '#', $replace_part $regex = '!'.$regex.'!ui'; + // if $replacement is a single character: replace each of the characters of the badword with $replacement if (UTF8::strlen($replacement) == 1) { - $regex .= 'e'; - return preg_replace($regex, 'str_repeat($replacement, UTF8::strlen(\'$1\'))', $str); + // issue #4819: use preg_replace_callback, preg_replace with /e modifier is depricated for PHP 5.5.0 + $callback = create_function('$matches', 'return str_repeat("' . $replacement . '", UTF8::strlen($matches[1]));'); + + return preg_replace_callback($regex, $callback, $str); } + // if $replacement is not a single character, fully replace the badword with $replacement return preg_replace($regex, $replacement, $str); } @@ -531,7 +538,7 @@ public static function number($number) { if ($number / $unit >= 1) { - // $value = the number of times the number is divisble by unit + // $value = the number of times the number is divisible by unit $number -= $unit * ($value = (int) floor($number / $unit)); // Temporary var for textifying the current unit $item = ''; @@ -587,20 +594,24 @@ public static function number($number) * * echo Text::widont($text); * + * regex courtesy of the Typogrify project + * @link http://code.google.com/p/typogrify/ + * * @param string $str text to remove widows from * @return string */ public static function widont($str) { - $str = rtrim($str); - $space = strrpos($str, ' '); - - if ($space !== FALSE) - { - $str = substr($str, 0, $space).' '.substr($str, $space + 1); - } - - return $str; + // use '%' as delimiter and 'x' as modifier + $widont_regex = "% + ((?:]*>)|[^<>\s]) # must be proceeded by an approved inline opening or closing tag or a nontag/nonspace + \s+ # the space to replace + ([^<>\s]+ # must be flollowed by non-tag non-space characters + \s* # optional white space! + (\s*)* # optional closing inline tags with optional white space after each + (()|$)) # end with a closing p, h1-6, li or the end of the string + %x"; + return preg_replace($widont_regex, '$1 $2', $str); } } // End text diff --git a/classes/kohana/utf8.php b/classes/kohana/utf8.php index 0447cc004..72fba8966 100644 --- a/classes/kohana/utf8.php +++ b/classes/kohana/utf8.php @@ -63,24 +63,29 @@ public static function clean($var, $charset = NULL) foreach ($var as $key => $val) { // Recursion! - $var[self::clean($key)] = self::clean($val); + $var[UTF8::clean($key)] = UTF8::clean($val); } } elseif (is_string($var) AND $var !== '') { // Remove control characters - $var = self::strip_ascii_ctrl($var); + $var = UTF8::strip_ascii_ctrl($var); - if ( ! self::is_ascii($var)) + if ( ! UTF8::is_ascii($var)) { - // Disable notices - $error_reporting = error_reporting(~E_NOTICE); - // iconv is expensive, so it is only used when needed - $var = iconv($charset, $charset.'//IGNORE', $var); + // Set the mb_substitute_character() value into temporary variable + $mb_substitute_character = mb_substitute_character(); + + // Disable substituting illigal characters with the default '?' character + mb_substitute_character('none'); + + // mb_convert_encoding is expensive, so it is only used when needed + $var = mb_convert_encoding($var, $charset, $charset); + + // Reset mb_substitute_character() value back to the original setting + mb_substitute_character($mb_substitute_character); - // Turn notices back on - error_reporting($error_reporting); } } @@ -144,12 +149,12 @@ public static function strip_non_ascii($str) */ public static function transliterate_to_ascii($str, $case = 0) { - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _transliterate_to_ascii($str, $case); @@ -170,12 +175,12 @@ public static function strlen($str) if (UTF8::$server_utf8) return mb_strlen($str, Kohana::$charset); - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _strlen($str); @@ -200,12 +205,12 @@ public static function strpos($str, $search, $offset = 0) if (UTF8::$server_utf8) return mb_strpos($str, $search, $offset, Kohana::$charset); - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _strpos($str, $search, $offset); @@ -230,12 +235,12 @@ public static function strrpos($str, $search, $offset = 0) if (UTF8::$server_utf8) return mb_strrpos($str, $search, $offset, Kohana::$charset); - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _strrpos($str, $search, $offset); @@ -262,12 +267,12 @@ public static function substr($str, $offset, $length = NULL) ? mb_substr($str, $offset, mb_strlen($str), Kohana::$charset) : mb_substr($str, $offset, $length, Kohana::$charset); - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _substr($str, $offset, $length); @@ -287,12 +292,12 @@ public static function substr($str, $offset, $length = NULL) */ public static function substr_replace($str, $replacement, $offset, $length = NULL) { - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _substr_replace($str, $replacement, $offset, $length); @@ -314,12 +319,12 @@ public static function strtolower($str) if (UTF8::$server_utf8) return mb_strtolower($str, Kohana::$charset); - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _strtolower($str); @@ -340,12 +345,12 @@ public static function strtoupper($str) if (UTF8::$server_utf8) return mb_strtoupper($str, Kohana::$charset); - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _strtoupper($str); @@ -363,12 +368,12 @@ public static function strtoupper($str) */ public static function ucfirst($str) { - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _ucfirst($str); @@ -387,12 +392,12 @@ public static function ucfirst($str) */ public static function ucwords($str) { - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _ucwords($str); @@ -413,12 +418,12 @@ public static function ucwords($str) */ public static function strcasecmp($str1, $str2) { - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _strcasecmp($str1, $str2); @@ -442,19 +447,19 @@ public static function strcasecmp($str1, $str2) */ public static function str_ireplace($search, $replace, $str, & $count = NULL) { - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _str_ireplace($search, $replace, $str, $count); } /** - * Case-insenstive UTF-8 version of strstr. Returns all of input string + * Case-insensitive UTF-8 version of strstr. Returns all of input string * from the first occurrence of needle to the end. This is a UTF8-aware * version of [stristr](http://php.net/stristr). * @@ -468,12 +473,12 @@ public static function str_ireplace($search, $replace, $str, & $count = NULL) */ public static function stristr($str, $search) { - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _stristr($str, $search); @@ -494,12 +499,12 @@ public static function stristr($str, $search) */ public static function strspn($str, $mask, $offset = NULL, $length = NULL) { - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _strspn($str, $mask, $offset, $length); @@ -520,12 +525,12 @@ public static function strspn($str, $mask, $offset = NULL, $length = NULL) */ public static function strcspn($str, $mask, $offset = NULL, $length = NULL) { - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _strcspn($str, $mask, $offset, $length); @@ -546,12 +551,12 @@ public static function strcspn($str, $mask, $offset = NULL, $length = NULL) */ public static function str_pad($str, $final_str_length, $pad_str = ' ', $pad_type = STR_PAD_RIGHT) { - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _str_pad($str, $final_str_length, $pad_str, $pad_type); @@ -570,12 +575,12 @@ public static function str_pad($str, $final_str_length, $pad_str = ' ', $pad_typ */ public static function str_split($str, $split_length = 1) { - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _str_split($str, $split_length); @@ -592,12 +597,12 @@ public static function str_split($str, $split_length = 1) */ public static function strrev($str) { - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _strrev($str); @@ -616,12 +621,12 @@ public static function strrev($str) */ public static function trim($str, $charlist = NULL) { - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _trim($str, $charlist); @@ -640,12 +645,12 @@ public static function trim($str, $charlist = NULL) */ public static function ltrim($str, $charlist = NULL) { - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _ltrim($str, $charlist); @@ -664,12 +669,12 @@ public static function ltrim($str, $charlist = NULL) */ public static function rtrim($str, $charlist = NULL) { - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _rtrim($str, $charlist); @@ -687,12 +692,12 @@ public static function rtrim($str, $charlist = NULL) */ public static function ord($chr) { - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _ord($chr); @@ -717,12 +722,12 @@ public static function ord($chr) */ public static function to_unicode($str) { - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _to_unicode($str); @@ -731,7 +736,7 @@ public static function to_unicode($str) /** * Takes an array of ints representing the Unicode characters and returns a UTF-8 string. * Astral planes are supported i.e. the ints in the input can be > 0xFFFF. - * Occurrances of the BOM are ignored. Surrogates are not allowed. + * Occurrences of the BOM are ignored. Surrogates are not allowed. * * $str = UTF8::to_unicode($array); * @@ -747,12 +752,12 @@ public static function to_unicode($str) */ public static function from_unicode($arr) { - if ( ! isset(self::$called[__FUNCTION__])) + if ( ! isset(UTF8::$called[__FUNCTION__])) { require Kohana::find_file('utf8', __FUNCTION__); // Function has been called - self::$called[__FUNCTION__] = TRUE; + UTF8::$called[__FUNCTION__] = TRUE; } return _from_unicode($arr); diff --git a/classes/kohana/validation.php b/classes/kohana/validation.php index 50c29eee1..1c8d8abb3 100644 --- a/classes/kohana/validation.php +++ b/classes/kohana/validation.php @@ -219,7 +219,7 @@ public function rule($field, $rule, array $params = NULL) if ($field !== TRUE AND ! isset($this->_labels[$field])) { // Set the field label to the field name - $this->_labels[$field] = preg_replace('/[^\pL]+/u', ' ', $field); + $this->_labels[$field] = $field; } // Store the rule and params for this rule @@ -430,6 +430,13 @@ public function check() } } + // Unbind all the automatic bindings to avoid memory leaks. + unset($this->_bound[':validation']); + unset($this->_bound[':data']); + unset($this->_bound[':field']); + unset($this->_bound[':value']); + + // Restore the data to its original form $this->_data = $original; diff --git a/guide/kohana/bootstrap.md b/guide/kohana/bootstrap.md index 2b8c26ad5..19379249a 100644 --- a/guide/kohana/bootstrap.md +++ b/guide/kohana/bootstrap.md @@ -52,7 +52,7 @@ You can add conditional statements to make the bootstrap have different values b /** * Set the environment status by the domain. */ -if (strpos($_SERVER['HTTP_HOST'], 'kohanaphp.com') !== FALSE) +if (strpos($_SERVER['HTTP_HOST'], 'kohanaframework.org') !== FALSE) { // We are live! Kohana::$environment = Kohana::PRODUCTION; @@ -66,7 +66,7 @@ if (strpos($_SERVER['HTTP_HOST'], 'kohanaphp.com') !== FALSE) ... [trimmed] */ Kohana::init(array( - 'base_url' => Kohana::$environment === Kohana::PRODUCTION ? '/' : '/kohanaphp.com/', + 'base_url' => Kohana::$environment === Kohana::PRODUCTION ? '/' : '/kohanaframework.org/', 'caching' => Kohana::$environment === Kohana::PRODUCTION, 'profile' => Kohana::$environment !== Kohana::PRODUCTION, 'index_file' => FALSE, diff --git a/guide/kohana/flow.md b/guide/kohana/flow.md index 81a2e54b1..76fdfe8cb 100644 --- a/guide/kohana/flow.md +++ b/guide/kohana/flow.md @@ -16,7 +16,7 @@ Every application follows the same flow: * Includes each module's `init.php` file, if it exists. * The `init.php` file can perform additional environment setup, including adding routes. 10. [Route::set] is called multiple times to define the [application routes](routing). - 11. [Request::instance] is called to start processing the request. + 11. [Request::factory] is called to start processing the request. 1. Checks each route that has been set until a match is found. 2. Creates the controller instance and passes the request to it. 3. Calls the [Controller::before] method. @@ -24,4 +24,4 @@ Every application follows the same flow: 5. Calls the [Controller::after] method. * The above 5 steps can be repeated multiple times when using [HMVC sub-requests](requests). 3. Application flow returns to index.php - 12. The main [Request] response is displayed \ No newline at end of file + 12. The main [Request] response is displayed diff --git a/guide/kohana/index.md b/guide/kohana/index.md index 102439634..32c308751 100644 --- a/guide/kohana/index.md +++ b/guide/kohana/index.md @@ -20,4 +20,4 @@ We are working very hard to provide complete documentation. To help improve the ## Unofficial Documentation -If you are having trouble finding an answer here, have a look through the [unofficial wiki](http://kerkness.ca/wiki/doku.php). Your answer may also be found by searching the [forum](http://forum.kohanaphp.com/) or [stackoverflow](http://stackoverflow.com/questions/tagged/kohana) followed by asking your question on either. Additionally, you can chat with the community of developers on the freenode [#kohana](irc://irc.freenode.net/kohana) IRC channel. \ No newline at end of file +If you are having trouble finding an answer here, have a look through the [unofficial wiki](http://kerkness.ca/wiki/doku.php). Your answer may also be found by searching the [forum](http://forum.kohanaframework.org/) or [stackoverflow](http://stackoverflow.com/questions/tagged/kohana) followed by asking your question on either. Additionally, you can chat with the community of developers on the freenode [#kohana](irc://irc.freenode.net/kohana) IRC channel. diff --git a/guide/kohana/menu.md b/guide/kohana/menu.md index 4f6140bfc..756406bcd 100644 --- a/guide/kohana/menu.md +++ b/guide/kohana/menu.md @@ -37,13 +37,11 @@ - [Database](security/database) - [Encryption](security/encryption) - [Deploying](security/deploying) -- [Tutorials](tutorials) +- Tutorials - [Hello World](tutorials/hello-world) - [Simple MVC](tutorials/simple-mvc) - [Custom Error Pages](tutorials/error-pages) - - [Content Translation](tutorials/translation) - [Clean URLs](tutorials/clean-urls) - [Sharing Kohana](tutorials/sharing-kohana) - [Kohana as a Library](tutorials/library-kohana) - - [Template Driven Site](tutorials/templates) - [Working with Git](tutorials/git) diff --git a/guide/kohana/mvc/controllers.md b/guide/kohana/mvc/controllers.md index 29414825a..47af6077b 100644 --- a/guide/kohana/mvc/controllers.md +++ b/guide/kohana/mvc/controllers.md @@ -55,7 +55,7 @@ You can also have a controller extend another controller to share common things, Every controller has the `$this->request` property which is the [Request] object that called the controller. You can use this to get information about the current request, as well as set the response body via `$this->response->body($ouput)`. -Here is a partial list of the properties and methods available to `$this->request`. These can also be accessed via `Request::instance()`, but `$this->request` is provided as a shortcut. See the [Request] class for more information on any of these. +Here is a partial list of the properties and methods available to `$this->request`. See the [Request] class for more information on any of these. Property/method | What it does --- | --- diff --git a/guide/kohana/routing.md b/guide/kohana/routing.md index 07c9f5f77..24c411552 100644 --- a/guide/kohana/routing.md +++ b/guide/kohana/routing.md @@ -248,14 +248,14 @@ Let's say you decided later to make that route definition more verbose by changi One method you might use frequently is the shortcut [Request::uri] which is the same as the above except it assumes the current route, directory, controller and action. If our current route is the default and the uri was `users/list`, we can do the following to generate uris in the format `users/view/$id`: - $this->request->uri(array('action' => 'view', 'id' => $user_id)); - + $this->request->route()->uri(array('action' => 'view', 'id' => $user_id)); + Or if within a view, the preferable method is: - Request::instance()->uri(array('action' => 'view', 'id' => $user_id)); + Route::url('default', array('action' => 'view', 'id' => $user_id)); TODO: examples of using html::anchor in addition to the above examples ## Testing routes -TODO: mention bluehawk's devtools module \ No newline at end of file +TODO: mention bluehawk's devtools module diff --git a/guide/kohana/tutorials.md b/guide/kohana/tutorials.md deleted file mode 100644 index c921bcd55..000000000 --- a/guide/kohana/tutorials.md +++ /dev/null @@ -1,17 +0,0 @@ -# Tutorials - -## Tutorials in this guide - -## Tutorials written elsewhere - -### Ellisgl's KO3 tutorial on dealtaker.com: - -1. [Install and Basic Usage](http://www.dealtaker.com/blog/2009/11/20/kohana-php-3-0-ko3-tutorial-part-1/) -2. [Views](http://www.dealtaker.com/blog/2009/12/07/kohana-php-3-0-ko3-tutorial-part-2/) -3. [Controllers](http://www.dealtaker.com/blog/2009/12/30/kohana-php-3-0-ko3-tutorial-part-3/) -4. [Models](http://www.dealtaker.com/blog/2010/02/01/kohana-php-3-0-ko3-tutorial-part-4/) -5. [Subrequests](http://www.dealtaker.com/blog/2010/02/25/kohana-php-3-0-ko3-tutorial-part-5/) -6. [Routes](http://www.dealtaker.com/blog/2010/03/03/kohana-php-3-0-ko3-tutorial-part-6/) -7. [Helpers](http://www.dealtaker.com/blog/2010/03/26/kohana-php-3-0-ko3-tutorial-part-7/) -8. [Modules](http://www.dealtaker.com/blog/2010/04/30/kohana-php-3-0-ko3-tutorial-part-8/) -9. [Vendor Libraries](http://www.dealtaker.com/blog/2010/06/02/kohana-php-3-0-ko3-tutorial-part-9/) \ No newline at end of file diff --git a/guide/kohana/tutorials/templates.md b/guide/kohana/tutorials/templates.md deleted file mode 100644 index 4bfd9c26b..000000000 --- a/guide/kohana/tutorials/templates.md +++ /dev/null @@ -1,7 +0,0 @@ -Making a template driven site. - - - - - - \ No newline at end of file diff --git a/guide/kohana/tutorials/translation.md b/guide/kohana/tutorials/translation.md deleted file mode 100644 index 12f7cfcf5..000000000 --- a/guide/kohana/tutorials/translation.md +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/guide/kohana/upgrading.md b/guide/kohana/upgrading.md index c09a5b00a..9dd2662af 100644 --- a/guide/kohana/upgrading.md +++ b/guide/kohana/upgrading.md @@ -58,6 +58,15 @@ Alternatively it is possible to set a specific client to an individual Request. ->client(new Request_Client_Stream) ->execute(); +## Generating URIs + +In Kohana 3.1, you could generate URIs by passing parameters to the `Request::uri` method. In Kohana 3.2 [Request::uri] +just returns the URI of the current route. URIs can **NOT** be generated using the `Request::uri` method anymore. + +Instead, you should generate your URIs by passing your parameters to the [Route::uri] method. + +For more information, please read the section about [creating URLs and links using routes](routing#creating-urls-and-links-using-routes). + ## HTTP cache control Kohana 3.1 introduced HTTP cache control, providing RFC 2616 fully compliant transparent caching of responses. Kohana 3.2 builds on this moving all caching logic out of `Request_Client` into `HTTP_Cache`. diff --git a/messages/validation.php b/messages/validation.php index dcaa38987..345a5e8e0 100644 --- a/messages/validation.php +++ b/messages/validation.php @@ -15,7 +15,7 @@ 'exact_length' => ':field must be exactly :param2 characters long', 'in_array' => ':field must be one of the available options', 'ip' => ':field must be an ip address', - 'matches' => ':field must be the same as :param2', + 'matches' => ':field must be the same as :param3', 'min_length' => ':field must be at least :param2 characters long', 'max_length' => ':field must not exceed :param2 characters long', 'not_empty' => ':field must not be empty', diff --git a/tests/kohana/ArrTest.php b/tests/kohana/ArrTest.php index 54bdc7cea..2260cd3c6 100644 --- a/tests/kohana/ArrTest.php +++ b/tests/kohana/ArrTest.php @@ -280,6 +280,42 @@ public function provider_merge() array('foo' => array('bar')), array('foo' => 'bar'), ), + /** + * @ticket 4482 + */ + array( + array( + 'foo' => array( + 'bar' => array( + 'foo' => TRUE, + array( + 'bar' => TRUE, + 'bar1' => FALSE, + ), + ), + ) + ), + array( + 'foo' => array( + 'bar' => array( + 'foo' => 'php', + array( + 'bar' => TRUE, + ), + ), + ), + ), + array( + 'foo' => array( + 'bar' => array( + 'foo' => TRUE, + array( + 'bar1' => FALSE, + ), + ), + ), + ) + ), ); } diff --git a/tests/kohana/Config/File/ReaderTest.php b/tests/kohana/Config/File/ReaderTest.php index ab22d14ae..7a365d183 100644 --- a/tests/kohana/Config/File/ReaderTest.php +++ b/tests/kohana/Config/File/ReaderTest.php @@ -11,7 +11,7 @@ * @author Jeremy Bush * @author Matt Button * @copyright (c) 2008-2012 Kohana Team - * @license http://kohanaphp.com/license + * @license http://kohanaframework.org/license */ class Kohana_Config_File_ReaderTest extends Kohana_Unittest_TestCase { diff --git a/tests/kohana/Config/GroupTest.php b/tests/kohana/Config/GroupTest.php index f18e44e1f..b78fbcfbc 100644 --- a/tests/kohana/Config/GroupTest.php +++ b/tests/kohana/Config/GroupTest.php @@ -11,7 +11,7 @@ * @author Jeremy Bush * @author Matt Button * @copyright (c) 2008-2012 Kohana Team - * @license http://kohanaphp.com/license + * @license http://kohanaframework.org/license */ class Kohana_Config_GroupTest extends Kohana_Unittest_TestCase { diff --git a/tests/kohana/CoreTest.php b/tests/kohana/CoreTest.php index 5f4adf0d8..cd70bd024 100644 --- a/tests/kohana/CoreTest.php +++ b/tests/kohana/CoreTest.php @@ -171,7 +171,7 @@ public function provider_message() 'exact_length' => ':field must be exactly :param2 characters long', 'in_array' => ':field must be one of the available options', 'ip' => ':field must be an ip address', - 'matches' => ':field must be the same as :param2', + 'matches' => ':field must be the same as :param3', 'min_length' => ':field must be at least :param2 characters long', 'max_length' => ':field must not exceed :param2 characters long', 'not_empty' => ':field must not be empty', diff --git a/tests/kohana/DebugTest.php b/tests/kohana/DebugTest.php index 218309db4..ed9d09b54 100644 --- a/tests/kohana/DebugTest.php +++ b/tests/kohana/DebugTest.php @@ -14,7 +14,7 @@ * @author Kohana Team * @author Jeremy Bush * @copyright (c) 2008-2012 Kohana Team - * @license http://kohanaphp.com/license + * @license http://kohanaframework.org/license */ class Kohana_DebugTest extends Unittest_TestCase { diff --git a/tests/kohana/Http/HeaderTest.php b/tests/kohana/Http/HeaderTest.php index c7dffdaa5..4c82172e2 100644 --- a/tests/kohana/Http/HeaderTest.php +++ b/tests/kohana/Http/HeaderTest.php @@ -12,7 +12,7 @@ * @category Tests * @author Kohana Team * @copyright (c) 2008-2012 Kohana Team - * @license http://kohanaphp.com/license + * @license http://kohanaframework.org/license */ class Kohana_HTTP_HeaderTest extends Unittest_TestCase { diff --git a/tests/kohana/RequestTest.php b/tests/kohana/RequestTest.php index 3941d5488..74c05e251 100644 --- a/tests/kohana/RequestTest.php +++ b/tests/kohana/RequestTest.php @@ -301,6 +301,12 @@ public function provider_url() TRUE, 'http://localhost/kohana/foo' ), + array( + 'http://www.google.com', + 'http', + TRUE, + 'http://www.google.com' + ), ); } @@ -310,10 +316,10 @@ public function provider_url() * @test * @dataProvider provider_url * @covers Request::url - * @param string $route the route to use - * @param array $params params to pass to route::uri - * @param string $protocol the protocol to use - * @param array $expected The string we expect + * @param string $uri the uri to use + * @param mixed $protocol the protocol to use (string or Request object) + * @param bool $is_cli whether the call is from CLI or not + * @param string $expected The url string we expect */ public function test_url($uri, $protocol, $is_cli, $expected) { @@ -329,7 +335,14 @@ public function test_url($uri, $protocol, $is_cli, $expected) 'Kohana::$is_cli' => $is_cli, )); - $this->assertEquals(Request::factory($uri)->url($protocol), $expected); + // issue #3967: inject the route so that we don't conflict with the application's default route + $route = new Route('((/))'); + $route->defaults(array( + 'controller' => 'welcome', + 'action' => 'index', + )); + + $this->assertEquals(Request::factory($uri, NULL, array($route))->url($protocol), $expected); } /** @@ -430,8 +443,15 @@ public function test_post_max_size_exceeded($content_length, $expected) */ public function provider_uri_only_trimed_on_internal() { + // issue #3967: inject the route so that we don't conflict with the application's default route + $route = new Route('((/))'); + $route->defaults(array( + 'controller' => 'welcome', + 'action' => 'index', + )); + $old_request = Request::$initial; - Request::$initial = new Request(TRUE); + Request::$initial = new Request(TRUE, NULL, array($route)); $result = array( array( diff --git a/tests/kohana/RouteTest.php b/tests/kohana/RouteTest.php index e57c45a9e..a4747ccd9 100644 --- a/tests/kohana/RouteTest.php +++ b/tests/kohana/RouteTest.php @@ -715,4 +715,43 @@ public function test_external_route_includes_params_in_uri($route, $defaults, $e $this->assertSame($expected_uri, Route::get('test')->uri()); } + + /** + * Provides test data for test_route_uri_encode_parameters + * + * @return array + */ + public function provider_route_uri_encode_parameters() + { + return array( + array( + 'article', + 'blog/article/', + array( + 'controller' => 'home', + 'action' => 'index' + ), + 'article_name', + 'Article name with special chars \\ ##', + 'blog/article/Article%20name%20with%20special%20chars%20\\%20%23%23' + ) + ); + } + + /** + * http://dev.kohanaframework.org/issues/4079 + * + * @test + * @covers Route::get + * @ticket 4079 + * @dataProvider provider_route_uri_encode_parameters + */ + public function test_route_uri_encode_parameters($name, $uri_callback, $defaults, $uri_key, $uri_value, $expected) + { + Route::set($name, $uri_callback)->defaults($defaults); + + $get_route_uri = Route::get($name)->uri(array($uri_key => $uri_value)); + + $this->assertSame($expected, $get_route_uri); + } } diff --git a/tests/kohana/TextTest.php b/tests/kohana/TextTest.php index 1d5d867c9..2084229c4 100644 --- a/tests/kohana/TextTest.php +++ b/tests/kohana/TextTest.php @@ -384,9 +384,90 @@ function provider_widont() { return array ( - array('No gain, no pain', 'No gain, no pain'), - array("spaces?what'rethey?", "spaces?what'rethey?"), - array('', ''), + // A very simple widont test + array( + 'A very simple test', + 'A very simple test', + ), + // Single word items shouldn't be changed + array( + 'Test', + 'Test', + ), + // Single word after single space shouldn't be changed either + array( + ' Test', + ' Test', + ), + // Single word with HTML all around + array( + '
  • Test

    • ', + '
      • Test

        • ', + ), + // Single word after single space with HTML all around + array( + '
          • Test

            • ', + '
              • Test

                • ', + ), + // Widont with more than one paragraph + array( + '

                  In a couple of paragraphs

                  paragraph two

                  ', + '

                  In a couple of paragraphs

                  paragraph two

                  ', + ), + // a link inside a heading + array( + '

                  In a link inside a heading

                  ', + '

                  In a link inside a heading

                  ', + ), + // a link followed by text + array( + '

                  In a link followed by other text

                  ', + '

                  In a link followed by other text

                  ', + ), + // empty html, with no text inside + array( + '

                  ', + '

                  ', + ), + // apparently, we don't love DIVs + array( + '
                  Divs get no love!
                  ', + '
                  Divs get no love!
                  ', + ), + // we don't love PREs, either + array( + '
                  Neither do PREs
                  ', + '
                  Neither do PREs
                  ', + ), + // but we love DIVs with paragraphs + array( + '

                  But divs with paragraphs do!

                  ', + '

                  But divs with paragraphs do!

                  ', + ), + array( + 'No gain, no pain', + 'No gain, no pain', + ), + array( + "spaces?what'rethey?", + "spaces?what'rethey?", + ), + /* + * // @issue 3499, with HTML at the end + * array( + * 'with HTML at the end  Kohana', + * 'with HTML at the end Kohana', + * ), + * // @issue 3499, with HTML with attributes at the end + * array( + * 'with HTML at the end: Kohana', + * 'with HTML at the end: Kohana', + * ), + */ + array( + '', + '', + ), ); } diff --git a/tests/kohana/ValidationTest.php b/tests/kohana/ValidationTest.php index 05258495a..6acb292fa 100644 --- a/tests/kohana/ValidationTest.php +++ b/tests/kohana/ValidationTest.php @@ -542,7 +542,7 @@ public function test_data_stays_unaltered() public function test_object_parameters_not_in_messages() { $validation = Validation::factory(array('foo' => 'foo')) - ->rule('bar', 'matches', array(':validation', 'foo', ':field')); + ->rule('bar', 'matches', array(':validation', ':field', 'foo')); $validation->check(); $errors = $validation->errors('validation'); @@ -665,4 +665,48 @@ public function test_error_type_check() $this->assertSame($errors, $validation->errors('validation')); } + /** + * Provides test data for test_rule_label_regex + * + * @return array + */ + public function provider_rule_label_regex() + { + // $data, $field, $rules, $expected + return array( + array( + array( + 'email1' => '', + ), + 'email1', + array( + array( + 'not_empty' + ) + ), + array( + 'email1' => 'email1 must not be empty' + ), + ) + ); + } + + /** + * http://dev.kohanaframework.org/issues/4201 + * + * @test + * @ticket 4201 + * @covers Validation::rule + * @dataProvider provider_rule_label_regex + */ + public function test_rule_label_regex($data, $field, $rules, $expected) + { + $validation = Validation::factory($data)->rules($field, $rules); + + $validation->check(); + + $errors = $validation->errors(''); + + $this->assertSame($errors, $expected); + } } diff --git a/utf8/ucwords.php b/utf8/ucwords.php index a266702fa..987b36bd1 100644 --- a/utf8/ucwords.php +++ b/utf8/ucwords.php @@ -15,9 +15,10 @@ function _ucwords($str) // [\x0c\x09\x0b\x0a\x0d\x20] matches form feeds, horizontal tabs, vertical tabs, linefeeds and carriage returns. // This corresponds to the definition of a 'word' defined at http://php.net/ucwords - return preg_replace( - '/(?<=^|[\x0c\x09\x0b\x0a\x0d\x20])[^\x0c\x09\x0b\x0a\x0d\x20]/ue', - 'UTF8::strtoupper(\'$0\')', + $callback = create_function('$matches', 'return UTF8::strtoupper($matches[0]);'); + return preg_replace_callback( + '/(?<=^|[\x0c\x09\x0b\x0a\x0d\x20])[^\x0c\x09\x0b\x0a\x0d\x20]/u', + $callback, $str ); -} \ No newline at end of file +} diff --git a/views/kohana/error.php b/views/kohana/error.php index e9f991b15..36ba2d5a2 100644 --- a/views/kohana/error.php +++ b/views/kohana/error.php @@ -48,7 +48,7 @@ function koggle(elem) }
                  -

                  [ ]:

                  +

                  [ ]:

                  [ ]

                  @@ -117,7 +117,7 @@ function koggle(elem) $value): ?> - + diff --git a/views/profiler/stats.php b/views/profiler/stats.php index ebfb489b7..f134cf824 100755 --- a/views/profiler/stats.php +++ b/views/profiler/stats.php @@ -35,7 +35,7 @@
                  s
                  -
                  +
                  @@ -47,7 +47,7 @@
                  kB
                  -
                  +
                  @@ -71,4 +71,4 @@
                  -
                  \ No newline at end of file +