diff --git a/app/Config/bootstrap.php b/app/Config/bootstrap.php
index fce18ccba..3b772c691 100644
--- a/app/Config/bootstrap.php
+++ b/app/Config/bootstrap.php
@@ -23,7 +23,66 @@
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
-// Setup a 'default' cache configuration for use in the application.
+/**
+ * Cache Engine Configuration
+ * Default settings provided below
+ *
+ * File storage engine.
+ *
+ * Cache::config('default', array(
+ * 'engine' => 'File', //[required]
+ * 'duration'=> 3600, //[optional]
+ * 'probability'=> 100, //[optional]
+ * 'path' => CACHE, //[optional] use system tmp directory - remember to use absolute path
+ * 'prefix' => 'cake_', //[optional] prefix every cache file with this string
+ * 'lock' => false, //[optional] use file locking
+ * 'serialize' => true, // [optional]
+ * 'mask' => 0666, // [optional] permission mask to use when creating cache files
+ * ));
+ *
+ * APC (http://pecl.php.net/package/APC)
+ *
+ * Cache::config('default', array(
+ * 'engine' => 'Apc', //[required]
+ * 'duration'=> 3600, //[optional]
+ * 'probability'=> 100, //[optional]
+ * 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
+ * ));
+ *
+ * Xcache (http://xcache.lighttpd.net/)
+ *
+ * Cache::config('default', array(
+ * 'engine' => 'Xcache', //[required]
+ * 'duration'=> 3600, //[optional]
+ * 'probability'=> 100, //[optional]
+ * 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
+ * 'user' => 'user', //user from xcache.admin.user settings
+ * 'password' => 'password', //plaintext password (xcache.admin.pass)
+ * ));
+ *
+ * Memcache (http://memcached.org/)
+ *
+ * Cache::config('default', array(
+ * 'engine' => 'Memcache', //[required]
+ * 'duration'=> 3600, //[optional]
+ * 'probability'=> 100, //[optional]
+ * 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
+ * 'servers' => array(
+ * '127.0.0.1:11211' // localhost, default port 11211
+ * ), //[optional]
+ * 'persistent' => true, // [optional] set this to false for non-persistent connections
+ * 'compress' => false, // [optional] compress data in Memcache (slower, but uses less memory)
+ * ));
+ *
+ * Wincache (http://php.net/wincache)
+ *
+ * Cache::config('default', array(
+ * 'engine' => 'Wincache', //[required]
+ * 'duration'=> 3600, //[optional]
+ * 'probability'=> 100, //[optional]
+ * 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
+ * ));
+ */
Cache::config('default', array('engine' => 'File'));
/**
diff --git a/app/Config/core.php b/app/Config/core.php
index 2989f13cd..771ed5b98 100644
--- a/app/Config/core.php
+++ b/app/Config/core.php
@@ -231,71 +231,13 @@
*/
//date_default_timezone_set('UTC');
-/**
- *
- * Cache Engine Configuration
- * Default settings provided below
- *
- * File storage engine.
- *
- * Cache::config('default', array(
- * 'engine' => 'File', //[required]
- * 'duration'=> 3600, //[optional]
- * 'probability'=> 100, //[optional]
- * 'path' => CACHE, //[optional] use system tmp directory - remember to use absolute path
- * 'prefix' => 'cake_', //[optional] prefix every cache file with this string
- * 'lock' => false, //[optional] use file locking
- * 'serialize' => true, [optional]
- * ));
- *
- * APC (http://pecl.php.net/package/APC)
- *
- * Cache::config('default', array(
- * 'engine' => 'Apc', //[required]
- * 'duration'=> 3600, //[optional]
- * 'probability'=> 100, //[optional]
- * 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
- * ));
- *
- * Xcache (http://xcache.lighttpd.net/)
- *
- * Cache::config('default', array(
- * 'engine' => 'Xcache', //[required]
- * 'duration'=> 3600, //[optional]
- * 'probability'=> 100, //[optional]
- * 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
- * 'user' => 'user', //user from xcache.admin.user settings
- * 'password' => 'password', //plaintext password (xcache.admin.pass)
- * ));
- *
- * Memcache (http://memcached.org/)
- *
- * Cache::config('default', array(
- * 'engine' => 'Memcache', //[required]
- * 'duration'=> 3600, //[optional]
- * 'probability'=> 100, //[optional]
- * 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
- * 'servers' => array(
- * '127.0.0.1:11211' // localhost, default port 11211
- * ), //[optional]
- * 'persistent' => true, // [optional] set this to false for non-persistent connections
- * 'compress' => false, // [optional] compress data in Memcache (slower, but uses less memory)
- * ));
- *
- * Wincache (http://php.net/wincache)
- *
- * Cache::config('default', array(
- * 'engine' => 'Wincache', //[required]
- * 'duration'=> 3600, //[optional]
- * 'probability'=> 100, //[optional]
- * 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
- * ));
- */
-
/**
* Pick the caching engine to use. If APC is enabled use it.
* If running via cli - apc is disabled by default. ensure it's available and enabled in this case
*
+ * Note: 'default' and other application caches should be configured in app/Config/bootstrap.php.
+ * Please check the comments in boostrap.php for more info on the cache engines available
+ * and their setttings.
*/
$engine = 'File';
if (extension_loaded('apc') && function_exists('apc_dec') && (php_sapi_name() !== 'cli' || ini_get('apc.enable_cli'))) {
diff --git a/app/View/Pages/home.ctp b/app/View/Pages/home.ctp
index 79644ae56..cb409a043 100644
--- a/app/View/Pages/home.ctp
+++ b/app/View/Pages/home.ctp
@@ -121,9 +121,9 @@ if (isset($filePresent)):
App::uses('Validation', 'Utility');
if (!Validation::alphaNumeric('cakephp')) {
echo '
';
- __d('cake_dev', 'PCRE has not been compiled with Unicode support.');
- echo '
';
- __d('cake_dev', 'Recompile PCRE with Unicode support by adding --enable-unicode-properties
when configuring');
+ echo __d('cake_dev', 'PCRE has not been compiled with Unicode support.');
+ echo '
';
+ echo __d('cake_dev', 'Recompile PCRE with Unicode support by adding --enable-unicode-properties
when configuring');
echo '
';
}
?>
diff --git a/lib/Cake/Console/Command/Task/ControllerTask.php b/lib/Cake/Console/Command/Task/ControllerTask.php
index 621b95cc8..c1178dcec 100644
--- a/lib/Cake/Console/Command/Task/ControllerTask.php
+++ b/lib/Cake/Console/Command/Task/ControllerTask.php
@@ -126,7 +126,7 @@ class ControllerTask extends BakeTask {
protected function _interactive() {
$this->interactive = true;
$this->hr();
- $this->out(__d('cake_console', "Bake Controller\nPath: %s", $this->path));
+ $this->out(__d('cake_console', "Bake Controller\nPath: %s", $this->getPath()));
$this->hr();
if (empty($this->connection)) {
diff --git a/lib/Cake/Console/Command/Task/ExtractTask.php b/lib/Cake/Console/Command/Task/ExtractTask.php
index ed28c196b..fad45e89a 100644
--- a/lib/Cake/Console/Command/Task/ExtractTask.php
+++ b/lib/Cake/Console/Command/Task/ExtractTask.php
@@ -70,12 +70,19 @@ class ExtractTask extends AppShell {
protected $_tokens = array();
/**
- * Extracted strings
+ * Extracted strings indexed by domain.
*
* @var array
*/
protected $_strings = array();
+/**
+ * Singular strings and their line numbers.
+ *
+ * @var array
+ */
+ protected $_lines = array();
+
/**
* Destination path
*
@@ -325,8 +332,10 @@ class ExtractTask extends AppShell {
if ($mapCount == count($strings)) {
extract(array_combine($map, $strings));
$domain = isset($domain) ? $domain : 'default';
+
$string = isset($plural) ? $singular . "\0" . $plural : $singular;
- $this->_strings[$domain][$string][$this->_file][] = $line;
+ $this->_strings[$domain][] = $string;
+ $this->_lines[$domain][$singular][$this->_file][] = $line;
} else {
$this->_markerError($this->_file, $line, $functionName, $count);
}
@@ -406,7 +415,8 @@ class ExtractTask extends AppShell {
$message = $rule;
}
if ($message) {
- $this->_strings[$domain][$message][$file][] = 'validation for field ' . $field;
+ $this->_strings[$domain][] = $message;
+ $this->_lines[$domain][$message][$file][] = 'validation for field ' . $field;
}
}
}
@@ -419,7 +429,16 @@ class ExtractTask extends AppShell {
*/
protected function _buildFiles() {
foreach ($this->_strings as $domain => $strings) {
- foreach ($strings as $string => $files) {
+ $added = array();
+ rsort($strings);
+
+ foreach ($strings as $i => $string) {
+ $plural = false;
+ $singular = $string;
+ if (strpos($string, "\0") !== false) {
+ list($singular, $plural) = explode("\0", $string);
+ }
+ $files = $this->_lines[$domain][$singular];
$occurrences = array();
foreach ($files as $file => $lines) {
$occurrences[] = $file . ':' . implode(';', $lines);
@@ -427,17 +446,21 @@ class ExtractTask extends AppShell {
$occurrences = implode("\n#: ", $occurrences);
$header = '#: ' . str_replace($this->_paths, '', $occurrences) . "\n";
- if (strpos($string, "\0") === false) {
+ if ($plural === false && !empty($added[$singular])) {
+ continue;
+ }
+
+ if ($plural === false) {
$sentence = "msgid \"{$string}\"\n";
$sentence .= "msgstr \"\"\n\n";
} else {
- list($singular, $plural) = explode("\0", $string);
$sentence = "msgid \"{$singular}\"\n";
$sentence .= "msgid_plural \"{$plural}\"\n";
$sentence .= "msgstr[0] \"\"\n";
$sentence .= "msgstr[1] \"\"\n\n";
}
+ $added[$singular] = true;
$this->_store($domain, $header, $sentence);
if ($domain != 'default' && $this->_merge) {
$this->_store('default', $header, $sentence);
diff --git a/lib/Cake/Console/Command/Task/FixtureTask.php b/lib/Cake/Console/Command/Task/FixtureTask.php
index 36c51e3d7..bf58cd4a7 100644
--- a/lib/Cake/Console/Command/Task/FixtureTask.php
+++ b/lib/Cake/Console/Command/Task/FixtureTask.php
@@ -137,7 +137,7 @@ class FixtureTask extends BakeTask {
protected function _interactive() {
$this->DbConfig->interactive = $this->Model->interactive = $this->interactive = true;
$this->hr();
- $this->out(__d('cake_console', "Bake Fixture\nPath: %s", $this->path));
+ $this->out(__d('cake_console', "Bake Fixture\nPath: %s", $this->getPath()));
$this->hr();
if (!isset($this->connection)) {
diff --git a/lib/Cake/Console/Command/Task/ModelTask.php b/lib/Cake/Console/Command/Task/ModelTask.php
index bcdbdda98..9f30eadac 100644
--- a/lib/Cake/Console/Command/Task/ModelTask.php
+++ b/lib/Cake/Console/Command/Task/ModelTask.php
@@ -190,7 +190,7 @@ class ModelTask extends BakeTask {
*/
protected function _interactive() {
$this->hr();
- $this->out(__d('cake_console', "Bake Model\nPath: %s", $this->path));
+ $this->out(__d('cake_console', "Bake Model\nPath: %s", $this->getPath()));
$this->hr();
$this->interactive = true;
diff --git a/lib/Cake/Console/Command/Task/TestTask.php b/lib/Cake/Console/Command/Task/TestTask.php
index ee4e1ab5e..21a2e3ff1 100644
--- a/lib/Cake/Console/Command/Task/TestTask.php
+++ b/lib/Cake/Console/Command/Task/TestTask.php
@@ -94,7 +94,7 @@ class TestTask extends BakeTask {
$this->interactive = true;
$this->hr();
$this->out(__d('cake_console', 'Bake Tests'));
- $this->out(__d('cake_console', 'Path: %s', $this->path));
+ $this->out(__d('cake_console', 'Path: %s', $this->getPath()));
$this->hr();
if ($type) {
diff --git a/lib/Cake/Console/Command/Task/ViewTask.php b/lib/Cake/Console/Command/Task/ViewTask.php
index b125d0791..4fe53b7ec 100644
--- a/lib/Cake/Console/Command/Task/ViewTask.php
+++ b/lib/Cake/Console/Command/Task/ViewTask.php
@@ -195,7 +195,7 @@ class ViewTask extends BakeTask {
*/
protected function _interactive() {
$this->hr();
- $this->out(sprintf("Bake View\nPath: %s", $this->path));
+ $this->out(sprintf("Bake View\nPath: %s", $this->getPath()));
$this->hr();
$this->DbConfig->interactive = $this->Controller->interactive = $this->interactive = true;
diff --git a/lib/Cake/Controller/Component/Auth/BaseAuthorize.php b/lib/Cake/Controller/Component/Auth/BaseAuthorize.php
index f4c33fe3d..00763ab84 100644
--- a/lib/Cake/Controller/Component/Auth/BaseAuthorize.php
+++ b/lib/Cake/Controller/Component/Auth/BaseAuthorize.php
@@ -108,11 +108,13 @@ abstract class BaseAuthorize {
*/
public function action($request, $path = '/:plugin/:controller/:action') {
$plugin = empty($request['plugin']) ? null : Inflector::camelize($request['plugin']) . '/';
- return str_replace(
+ $path = str_replace(
array(':controller', ':action', ':plugin/'),
array(Inflector::camelize($request['controller']), $request['action'], $plugin),
$this->settings['actionPath'] . $path
);
+ $path = str_replace('//', '/', $path);
+ return trim($path, '/');
}
/**
diff --git a/lib/Cake/Controller/Component/CookieComponent.php b/lib/Cake/Controller/Component/CookieComponent.php
index cea188349..3abb24ddc 100644
--- a/lib/Cake/Controller/Component/CookieComponent.php
+++ b/lib/Cake/Controller/Component/CookieComponent.php
@@ -483,7 +483,8 @@ class CookieComponent extends Component {
* @return array Map of key and values
*/
protected function _explode($string) {
- if ($string[0] === '{' || $string[0] === '[') {
+ $first = substr($string, 0, 1);
+ if ($first !== false && $first === '{' || $first === '[') {
$ret = json_decode($string, true);
return ($ret != null) ? $ret : $string;
}
diff --git a/lib/Cake/Controller/Component/RequestHandlerComponent.php b/lib/Cake/Controller/Component/RequestHandlerComponent.php
index 6ca9b073f..c6f8f261c 100644
--- a/lib/Cake/Controller/Component/RequestHandlerComponent.php
+++ b/lib/Cake/Controller/Component/RequestHandlerComponent.php
@@ -160,7 +160,10 @@ class RequestHandlerComponent extends Component {
* switched based on the parsed extension or Accept-Type header. For example, if `controller/action.xml`
* is requested, the view path becomes `app/View/Controller/xml/action.ctp`. Also if
* `controller/action` is requested with `Accept-Type: application/xml` in the headers
- * the view path will become `app/View/Controller/xml/action.ctp`.
+ * the view path will become `app/View/Controller/xml/action.ctp`. Layout and template
+ * types will only switch to mime-types recognized by CakeResponse. If you need to declare
+ * additional mime-types, you can do so using CakeResponse::type() in your controllers beforeFilter()
+ * method.
* - If a helper with the same name as the extension exists, it is added to the controller.
* - If the extension is of a type that RequestHandler understands, it will set that
* Content-type in the response header.
diff --git a/lib/Cake/Core/App.php b/lib/Cake/Core/App.php
index b105b0633..6d37fbd3e 100644
--- a/lib/Cake/Core/App.php
+++ b/lib/Cake/Core/App.php
@@ -860,7 +860,7 @@ class App {
),
'Vendor' => array(
'%s' . 'Vendor' . DS,
- VENDORS
+ dirname(dirname(CAKE)) . DS . 'vendors' . DS,
),
'Plugin' => array(
APP . 'Plugin' . DS,
diff --git a/lib/Cake/Error/ErrorHandler.php b/lib/Cake/Error/ErrorHandler.php
index 2c2a2ee09..5899a71b4 100644
--- a/lib/Cake/Error/ErrorHandler.php
+++ b/lib/Cake/Error/ErrorHandler.php
@@ -217,6 +217,7 @@ class ErrorHandler {
$log = LOG_NOTICE;
break;
case E_DEPRECATED:
+ case E_USER_DEPRECATED:
$error = 'Deprecated';
$log = LOG_NOTICE;
break;
diff --git a/lib/Cake/Model/Datasource/Database/Sqlserver.php b/lib/Cake/Model/Datasource/Database/Sqlserver.php
index b903d8998..9b51bfad8 100644
--- a/lib/Cake/Model/Datasource/Database/Sqlserver.php
+++ b/lib/Cake/Model/Datasource/Database/Sqlserver.php
@@ -745,7 +745,7 @@ class Sqlserver extends DboSource {
*/
protected function _execute($sql, $params = array(), $prepareOptions = array()) {
$this->_lastAffected = false;
- if (strncasecmp($sql, 'SELECT', 6) == 0) {
+ if (strncasecmp($sql, 'SELECT', 6) == 0 || preg_match('/^EXEC(?:UTE)?\s/mi', $sql) > 0) {
$prepareOptions += array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL);
return parent::_execute($sql, $params, $prepareOptions);
}
diff --git a/lib/Cake/Model/Model.php b/lib/Cake/Model/Model.php
index 8986405f0..79acfbad3 100644
--- a/lib/Cake/Model/Model.php
+++ b/lib/Cake/Model/Model.php
@@ -2662,6 +2662,10 @@ class Model extends Object implements CakeEventListener {
protected function _findCount($state, $query, $results = array()) {
if ($state === 'before') {
$db = $this->getDataSource();
+ $query['order'] = false;
+ if (!method_exists($db, 'calculate') || !method_exists($db, 'expression')) {
+ return $query;
+ }
if (empty($query['fields'])) {
$query['fields'] = $db->calculate($this, 'count');
} elseif (is_string($query['fields']) && !preg_match('/count/i', $query['fields'])) {
@@ -2669,7 +2673,6 @@ class Model extends Object implements CakeEventListener {
$db->expression($query['fields']), 'count'
));
}
- $query['order'] = false;
return $query;
} elseif ($state === 'after') {
foreach (array(0, $this->alias) as $key) {
diff --git a/lib/Cake/Network/CakeResponse.php b/lib/Cake/Network/CakeResponse.php
index 539ec797a..cedefee39 100644
--- a/lib/Cake/Network/CakeResponse.php
+++ b/lib/Cake/Network/CakeResponse.php
@@ -208,6 +208,7 @@ class CakeResponse {
'hh' => 'text/plain',
'html' => array('text/html', '*/*'),
'htm' => array('text/html', '*/*'),
+ 'ics' => 'text/calendar',
'm' => 'text/plain',
'rtf' => 'text/rtf',
'rtx' => 'text/richtext',
diff --git a/lib/Cake/Network/Email/CakeEmail.php b/lib/Cake/Network/Email/CakeEmail.php
index 69c3982c2..c9aaf72ce 100644
--- a/lib/Cake/Network/Email/CakeEmail.php
+++ b/lib/Cake/Network/Email/CakeEmail.php
@@ -686,6 +686,9 @@ class CakeEmail {
if ($email === $alias) {
$return[] = $email;
} else {
+ if (strpos($alias, ',') !== false) {
+ $alias = '"' . $alias . '"';
+ }
$return[] = sprintf('%s <%s>', $this->_encode($alias), $email);
}
}
@@ -1109,9 +1112,6 @@ class CakeEmail {
$restore = mb_internal_encoding();
mb_internal_encoding($this->_appCharset);
}
- if (strpos($text, ',') !== false) {
- $text = '"' . $text . '"';
- }
$return = mb_encode_mimeheader($text, $this->headerCharset, 'B');
if ($internalEncoding) {
mb_internal_encoding($restore);
diff --git a/lib/Cake/Routing/Router.php b/lib/Cake/Routing/Router.php
index 2a211f7b4..f382ad26a 100644
--- a/lib/Cake/Routing/Router.php
+++ b/lib/Cake/Routing/Router.php
@@ -1077,15 +1077,17 @@ class Router {
* Instructs the router to parse out file extensions from the URL. For example,
* http://example.com/posts.rss would yield an file extension of "rss".
* The file extension itself is made available in the controller as
- * $this->params['url']['ext'], and is used by the RequestHandler component to
+ * `$this->params['ext']`, and is used by the RequestHandler component to
* automatically switch to alternate layouts and templates, and load helpers
- * corresponding to the given content, i.e. RssHelper.
+ * corresponding to the given content, i.e. RssHelper. Switching layouts and helpers
+ * requires that the chosen extension has a defined mime type in `CakeResponse`
*
* A list of valid extension can be passed to this method, i.e. Router::parseExtensions('rss', 'xml');
* If no parameters are given, anything after the first . (dot) after the last / in the URL will be
* parsed, excluding querystring parameters (i.e. ?q=...).
*
* @return void
+ * @see RequestHandler::startup()
*/
public static function parseExtensions() {
self::$_parseExtensions = true;
diff --git a/lib/Cake/Test/Case/Console/Command/Task/ExtractTaskTest.php b/lib/Cake/Test/Case/Console/Command/Task/ExtractTaskTest.php
index 15e0254ee..d358c7540 100644
--- a/lib/Cake/Test/Case/Console/Command/Task/ExtractTaskTest.php
+++ b/lib/Cake/Test/Case/Console/Command/Task/ExtractTaskTest.php
@@ -93,27 +93,37 @@ class ExtractTaskTest extends CakeTestCase {
// home.ctp
$pattern = '/msgid "Your tmp directory is writable."\nmsgstr ""\n/';
$this->assertRegExp($pattern, $result);
+
$pattern = '/msgid "Your tmp directory is NOT writable."\nmsgstr ""\n/';
$this->assertRegExp($pattern, $result);
+
$pattern = '/msgid "The %s is being used for caching. To change the config edit ';
$pattern .= 'APP\/config\/core.php "\nmsgstr ""\n/';
$this->assertRegExp($pattern, $result);
+
$pattern = '/msgid "Your cache is NOT working. Please check ';
$pattern .= 'the settings in APP\/config\/core.php"\nmsgstr ""\n/';
$this->assertRegExp($pattern, $result);
+
$pattern = '/msgid "Your database configuration file is present."\nmsgstr ""\n/';
$this->assertRegExp($pattern, $result);
+
$pattern = '/msgid "Your database configuration file is NOT present."\nmsgstr ""\n/';
$this->assertRegExp($pattern, $result);
+
$pattern = '/msgid "Rename config\/database.php.default to ';
$pattern .= 'config\/database.php"\nmsgstr ""\n/';
$this->assertRegExp($pattern, $result);
+
$pattern = '/msgid "Cake is able to connect to the database."\nmsgstr ""\n/';
$this->assertRegExp($pattern, $result);
+
$pattern = '/msgid "Cake is NOT able to connect to the database."\nmsgstr ""\n/';
$this->assertRegExp($pattern, $result);
+
$pattern = '/msgid "Editing this Page"\nmsgstr ""\n/';
$this->assertRegExp($pattern, $result);
+
$pattern = '/msgid "To change the content of this page, create: APP\/views\/pages\/home\.ctp/';
$this->assertRegExp($pattern, $result);
@@ -121,10 +131,13 @@ class ExtractTaskTest extends CakeTestCase {
$this->assertRegExp($pattern, $result);
// extract.ctp
- $pattern = '/\#: (\\\\|\/)extract\.ctp:6\n';
+ $pattern = '/\#: (\\\\|\/)extract\.ctp:15;6\n';
$pattern .= 'msgid "You have %d new message."\nmsgid_plural "You have %d new messages."/';
$this->assertRegExp($pattern, $result);
+ $pattern = '/msgid "You have %d new message."\nmsgstr ""/';
+ $this->assertNotRegExp($pattern, $result, 'No duplicate msgid');
+
$pattern = '/\#: (\\\\|\/)extract\.ctp:7\n';
$pattern .= 'msgid "You deleted %d message."\nmsgid_plural "You deleted %d messages."/';
$this->assertRegExp($pattern, $result);
@@ -134,7 +147,7 @@ class ExtractTaskTest extends CakeTestCase {
$pattern .= 'msgid "Editing this Page"\nmsgstr ""/';
$this->assertRegExp($pattern, $result);
- $pattern = '/\#: (\\\\|\/)extract\.ctp:17\nmsgid "';
+ $pattern = '/\#: (\\\\|\/)extract\.ctp:18\nmsgid "';
$pattern .= 'Hot features!';
$pattern .= '\\\n - No Configuration: Set-up the database and let the magic begin';
$pattern .= '\\\n - Extremely Simple: Just look at the name...It\'s Cake';
diff --git a/lib/Cake/Test/Case/Controller/Component/Auth/ActionsAuthorizeTest.php b/lib/Cake/Test/Case/Controller/Component/Auth/ActionsAuthorizeTest.php
index 5861bfe03..dc3afda78 100644
--- a/lib/Cake/Test/Case/Controller/Component/Auth/ActionsAuthorizeTest.php
+++ b/lib/Cake/Test/Case/Controller/Component/Auth/ActionsAuthorizeTest.php
@@ -75,7 +75,7 @@ class ActionsAuthorizeTest extends CakeTestCase {
$this->Acl->expects($this->once())
->method('check')
- ->with($user, '/controllers/Posts/index')
+ ->with($user, 'controllers/Posts/index')
->will($this->returnValue(false));
$this->assertFalse($this->auth->authorize($user['User'], $request));
@@ -104,7 +104,7 @@ class ActionsAuthorizeTest extends CakeTestCase {
$this->Acl->expects($this->once())
->method('check')
- ->with($user, '/controllers/Posts/index')
+ ->with($user, 'controllers/Posts/index')
->will($this->returnValue(true));
$this->assertTrue($this->auth->authorize($user['User'], $request));
@@ -134,7 +134,7 @@ class ActionsAuthorizeTest extends CakeTestCase {
$expected = array('TestPlugin.TestPluginAuthUser' => array('id' => 1, 'user' => 'mariano'));
$this->Acl->expects($this->once())
->method('check')
- ->with($expected, '/controllers/Posts/index')
+ ->with($expected, 'controllers/Posts/index')
->will($this->returnValue(true));
$this->assertTrue($this->auth->authorize($user, $request));
@@ -154,8 +154,23 @@ class ActionsAuthorizeTest extends CakeTestCase {
));
$result = $this->auth->action($request);
+ $this->assertEquals('controllers/Posts/index', $result);
+ }
- $this->assertEquals('/controllers/Posts/index', $result);
+/**
+ * Make sure that action() doesn't create double slashes anywhere.
+ *
+ * @return void
+ */
+ public function testActionNoDoubleSlash() {
+ $this->auth->settings['actionPath'] = '/controllers/';
+ $request = array(
+ 'plugin' => null,
+ 'controller' => 'posts',
+ 'action' => 'index'
+ );
+ $result = $this->auth->action($request);
+ $this->assertEquals('controllers/Posts/index', $result);
}
/**
@@ -172,6 +187,6 @@ class ActionsAuthorizeTest extends CakeTestCase {
));
$result = $this->auth->action($request);
- $this->assertEquals('/controllers/DebugKit/Posts/index', $result);
+ $this->assertEquals('controllers/DebugKit/Posts/index', $result);
}
}
diff --git a/lib/Cake/Test/Case/Controller/Component/CookieComponentTest.php b/lib/Cake/Test/Case/Controller/Component/CookieComponentTest.php
index 56fe5b645..701973dab 100644
--- a/lib/Cake/Test/Case/Controller/Component/CookieComponentTest.php
+++ b/lib/Cake/Test/Case/Controller/Component/CookieComponentTest.php
@@ -471,6 +471,21 @@ class CookieComponentTest extends CakeTestCase {
$this->assertEquals($expected, $result);
}
+/**
+ * Test reading empty values.
+ */
+ public function testReadEmpty() {
+ $_COOKIE['CakeTestCookie'] = array(
+ 'JSON' => '{"name":"value"}',
+ 'Empty' => '',
+ 'String' => '{"somewhat:"broken"}'
+ );
+ $this->assertEqual(array('name' => 'value'), $this->Cookie->read('JSON'));
+ $this->assertEqual('value', $this->Cookie->read('JSON.name'));
+ $this->assertEqual('', $this->Cookie->read('Empty'));
+ $this->assertEqual('{"somewhat:"broken"}', $this->Cookie->read('String'));
+ }
+
/**
* test that no error is issued for non array data.
*
@@ -483,6 +498,7 @@ class CookieComponentTest extends CakeTestCase {
$this->assertNull($this->Cookie->read('value'));
}
+
/**
* test that deleting a top level keys kills the child elements too.
*
diff --git a/lib/Cake/Test/Case/Model/Datasource/Database/SqlserverTest.php b/lib/Cake/Test/Case/Model/Datasource/Database/SqlserverTest.php
index 95394bf62..c01678c68 100644
--- a/lib/Cake/Test/Case/Model/Datasource/Database/SqlserverTest.php
+++ b/lib/Cake/Test/Case/Model/Datasource/Database/SqlserverTest.php
@@ -633,4 +633,31 @@ class SqlserverTest extends CakeTestCase {
$this->assertEquals('nate', $results[1]['User']['user']);
}
+/**
+ * Test that the return of stored procedures is honoured
+ *
+ * @return void
+ */
+ public function testStoredProcedureReturn() {
+ $sql = <<Dbo->execute($sql);
+
+ $sql = <<Dbo->execute($sql);
+ $this->Dbo->execute('DROP PROC cake_test_procedure');
+
+ $result = $query->fetch();
+ $this->assertEquals(2, $result['value']);
+ }
+
}
diff --git a/lib/Cake/Test/Case/Model/ModelDeleteTest.php b/lib/Cake/Test/Case/Model/ModelDeleteTest.php
index 9ce2e0717..e3a64e0b1 100644
--- a/lib/Cake/Test/Case/Model/ModelDeleteTest.php
+++ b/lib/Cake/Test/Case/Model/ModelDeleteTest.php
@@ -555,7 +555,9 @@ class ModelDeleteTest extends BaseModelTest {
* @return void
*/
public function testDeleteDependent() {
- $this->loadFixtures('Bidding', 'BiddingMessage');
+ $this->loadFixtures('Bidding', 'BiddingMessage', 'Article',
+ 'ArticlesTag', 'Comment', 'User', 'Attachment'
+ );
$Bidding = new Bidding();
$result = $Bidding->find('all');
$expected = array(
@@ -626,6 +628,20 @@ class ModelDeleteTest extends BaseModelTest {
),
);
$this->assertEquals($expected, $result);
+
+ $Article = new Article();
+ $result = $Article->Comment->find('count', array(
+ 'conditions' => array('Comment.article_id' => 1)
+ ));
+ $this->assertEquals(4, $result);
+
+ $result = $Article->delete(1, true);
+ $this->assertIdentical(true, true);
+
+ $result = $Article->Comment->find('count', array(
+ 'conditions' => array('Comment.article_id' => 1)
+ ));
+ $this->assertEquals(0, $result);
}
/**
diff --git a/lib/Cake/Test/Case/Network/Email/CakeEmailTest.php b/lib/Cake/Test/Case/Network/Email/CakeEmailTest.php
index a962bab1c..3c8c0d0fb 100644
--- a/lib/Cake/Test/Case/Network/Email/CakeEmailTest.php
+++ b/lib/Cake/Test/Case/Network/Email/CakeEmailTest.php
@@ -395,6 +395,8 @@ class CakeEmailTest extends CakeTestCase {
$this->CakeEmail->subject('You have a new message.');
$this->assertSame($this->CakeEmail->subject(), 'You have a new message.');
+ $this->CakeEmail->subject('You have a new message, I think.');
+ $this->assertSame($this->CakeEmail->subject(), 'You have a new message, I think.');
$this->CakeEmail->subject(1);
$this->assertSame($this->CakeEmail->subject(), '1');
diff --git a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php
index 40f1ff4f8..33732b2ac 100644
--- a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php
+++ b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php
@@ -1462,6 +1462,31 @@ class FormHelperTest extends CakeTestCase {
$this->assertEquals(array(), $this->Form->fields);
}
+/**
+ * testTagIsInvalid method
+ *
+ * @return void
+ */
+ public function testTagIsInvalid() {
+ $Contact = ClassRegistry::getObject('Contact');
+ $Contact->validationErrors[0]['email'] = array('Please provide an email');
+
+ $this->Form->setEntity('Contact.0.email');
+ $result = $this->Form->tagIsInvalid();
+ $expected = array('Please provide an email');
+ $this->assertEquals($expected, $result);
+
+ $this->Form->setEntity('Contact.1.email');
+ $result = $this->Form->tagIsInvalid();
+ $expected = false;
+ $this->assertIdentical($expected, $result);
+
+ $this->Form->setEntity('Contact.0.name');
+ $result = $this->Form->tagIsInvalid();
+ $expected = false;
+ $this->assertIdentical($expected, $result);
+ }
+
/**
* testPasswordValidation method
*
diff --git a/lib/Cake/Test/Case/View/MediaViewTest.php b/lib/Cake/Test/Case/View/MediaViewTest.php
index d1377ee20..38d68a239 100644
--- a/lib/Cake/Test/Case/View/MediaViewTest.php
+++ b/lib/Cake/Test/Case/View/MediaViewTest.php
@@ -244,6 +244,7 @@ class MediaViewTest extends CakeTestCase {
'path' => CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS,
'id' => 'no_section.ini',
'extension' => 'ini',
+ 'name' => 'config'
);
$this->MediaView->expects($this->exactly(2))
->method('_isActive')
@@ -270,7 +271,7 @@ class MediaViewTest extends CakeTestCase {
$this->MediaView->response->expects($this->once())
->method('download')
- ->with('no_section.ini');
+ ->with('config.ini');
$this->MediaView->response->expects($this->at(4))
->method('header')
@@ -357,7 +358,7 @@ class MediaViewTest extends CakeTestCase {
*
* @return void
*/
- function testRenderUpperExtesnion() {
+ public function testRenderUpperExtension() {
$this->MediaView->viewVars = array(
'path' => CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS .'img' . DS,
'id' => 'test_2.JPG',
@@ -376,4 +377,27 @@ class MediaViewTest extends CakeTestCase {
$this->MediaView->render();
}
+/**
+ * Test downloading files with extension not explicitly set.
+ *
+ * @return void
+ */
+ public function testRenderExtensionNotSet() {
+ $this->MediaView->viewVars = array(
+ 'path' => CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS .'img' . DS,
+ 'id' => 'test_2.JPG',
+ );
+
+ $this->MediaView->response->expects($this->any())
+ ->method('type')
+ ->with('jpg')
+ ->will($this->returnArgument(0));
+
+ $this->MediaView->expects($this->at(0))
+ ->method('_isActive')
+ ->will($this->returnValue(true));
+
+ $this->MediaView->render();
+ }
+
}
diff --git a/lib/Cake/Test/test_app/View/Pages/extract.ctp b/lib/Cake/Test/test_app/View/Pages/extract.ctp
index 5e6abf54e..cba9b012f 100644
--- a/lib/Cake/Test/test_app/View/Pages/extract.ctp
+++ b/lib/Cake/Test/test_app/View/Pages/extract.ctp
@@ -12,6 +12,7 @@ echo __dn('domain', 'You deleted %d message (domain).', 'You deleted %d messages
// Duplicated Message
echo __('Editing this Page');
+echo __('You have %d new message.');
// Multiline
__('Hot features!'
diff --git a/lib/Cake/Utility/Debugger.php b/lib/Cake/Utility/Debugger.php
index 34e85df41..a32a8e748 100644
--- a/lib/Cake/Utility/Debugger.php
+++ b/lib/Cake/Utility/Debugger.php
@@ -241,6 +241,11 @@ class Debugger {
$error = 'Notice';
$level = LOG_NOTICE;
break;
+ case E_DEPRECATED:
+ case E_USER_DEPRECATED:
+ $error = 'Deprecated';
+ $level = LOG_NOTICE;
+ break;
default:
return;
break;
@@ -805,5 +810,4 @@ class Debugger {
trigger_error(__d('cake_dev', 'Please change the value of \'Security.cipherSeed\' in app/Config/core.php to a numeric (digits only) seed value specific to your application'), E_USER_NOTICE);
}
}
-
}
diff --git a/lib/Cake/View/Helper/FormHelper.php b/lib/Cake/View/Helper/FormHelper.php
index 95d4d80e2..15089517d 100644
--- a/lib/Cake/View/Helper/FormHelper.php
+++ b/lib/Cake/View/Helper/FormHelper.php
@@ -272,8 +272,8 @@ class FormHelper extends AppHelper {
* Returns false if given form field described by the current entity has no errors.
* Otherwise it returns the validation message
*
- * @return mixed Either false when there or no errors, or the error
- * string. The error string could be ''.
+ * @return mixed Either false when there or no errors, or an array of error
+ * strings. An error string could be ''.
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::tagIsInvalid
*/
public function tagIsInvalid() {
@@ -289,8 +289,8 @@ class FormHelper extends AppHelper {
if (empty($errors)) {
return false;
}
- $error = Set::classicExtract($errors, join('.', $entity));
- return $error === null ? false : $error;
+ $errors = Set::classicExtract($errors, join('.', $entity));
+ return $errors === null ? false : $errors;
}
/**
@@ -739,7 +739,7 @@ class FormHelper extends AppHelper {
*
* ### Options
*
- * - `for` - Set the for attribute, if its not defined the for attribute
+ * - `for` - Set the for attribute, if its not defined the for attribute
* will be generated from the $fieldName parameter using
* FormHelper::domId().
*
@@ -776,8 +776,8 @@ class FormHelper extends AppHelper {
* }}}
*
* @param string $fieldName This should be "Modelname.fieldname"
- * @param string $text Text that will appear in the label field. If
- * $text is left undefined the text will be inflected from the
+ * @param string $text Text that will appear in the label field. If
+ * $text is left undefined the text will be inflected from the
* fieldName.
* @param mixed $options An array of HTML attributes, or a string, to be used as a class name.
* @return string The formatted LABEL element
diff --git a/lib/Cake/View/MediaView.php b/lib/Cake/View/MediaView.php
index 81b7dbf45..822e2beb8 100644
--- a/lib/Cake/View/MediaView.php
+++ b/lib/Cake/View/MediaView.php
@@ -31,9 +31,11 @@ App::uses('CakeRequest', 'Network');
* - `id` The filename on the server's filesystem, including extension.
* - `name` The filename that will be sent to the user, specified without the extension.
* - `download` Set to true to set a `Content-Disposition` header. This is ideal for file downloads.
- * - `extension` The extension of the file being served. This is used to set the mimetype
+ * - `extension` The extension of the file being served. This is used to set the mimetype.
+ * If not provided its extracted from filename provided as `id`.
* - `path` The absolute path, including the trailing / on the server's filesystem to `id`.
* - `mimeType` The mime type of the file if CakeResponse doesn't know about it.
+ * Must be an associative array with extension as key and mime type as value eg. array('ini' => 'text/plain')
*
* ### Usage
*
@@ -101,7 +103,11 @@ class MediaView extends View {
$this->response->type($mimeType);
}
- if (isset($extension) && $this->_isActive()) {
+ if (!isset($extension)) {
+ $extension = pathinfo($id, PATHINFO_EXTENSION);
+ }
+
+ if ($this->_isActive()) {
$extension = strtolower($extension);
$chunkSize = 8192;
$buffer = '';
@@ -116,7 +122,7 @@ class MediaView extends View {
} else {
$modified = time();
}
- if ($this->response->type($extension) === false) {
+ if (!$extension || $this->response->type($extension) === false) {
$download = true;
}
@@ -145,6 +151,8 @@ class MediaView extends View {
}
if (is_null($name)) {
$name = $id;
+ } elseif ($extension) {
+ $name .= '.' . $extension;
}
$this->response->download($name);
$this->response->header(array('Accept-Ranges' => 'bytes'));
diff --git a/lib/Cake/bootstrap.php b/lib/Cake/bootstrap.php
index 17f647784..f34b4001e 100644
--- a/lib/Cake/bootstrap.php
+++ b/lib/Cake/bootstrap.php
@@ -23,6 +23,10 @@ define('TIME_START', microtime(true));
if (!defined('E_DEPRECATED')) {
define('E_DEPRECATED', 8192);
}
+
+if (!defined('E_USER_DEPRECATED')) {
+ define('E_USER_DEPRECATED', E_USER_NOTICE);
+}
error_reporting(E_ALL & ~E_DEPRECATED);
if (!defined('CAKE_CORE_INCLUDE_PATH')) {