Merge branch '2.0' into 2.1

Conflicts:
	app/View/Pages/home.ctp
	lib/Cake/Config/config.php
	lib/Cake/Core/App.php
	lib/Cake/VERSION.txt
	lib/Cake/View/Helper/NumberHelper.php
This commit is contained in:
mark_story 2012-02-12 10:06:13 -05:00
commit 2afb05b590
32 changed files with 300 additions and 108 deletions

View file

@ -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'));
/**

View file

@ -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'))) {

View file

@ -121,9 +121,9 @@ if (isset($filePresent)):
App::uses('Validation', 'Utility');
if (!Validation::alphaNumeric('cakephp')) {
echo '<p><span class="notice">';
__d('cake_dev', 'PCRE has not been compiled with Unicode support.');
echo '<br/>';
__d('cake_dev', 'Recompile PCRE with Unicode support by adding <code>--enable-unicode-properties</code> when configuring');
echo __d('cake_dev', 'PCRE has not been compiled with Unicode support.');
echo '<br/>';
echo __d('cake_dev', 'Recompile PCRE with Unicode support by adding <code>--enable-unicode-properties</code> when configuring');
echo '</span></p>';
}
?>

View file

@ -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)) {

View file

@ -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);

View file

@ -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)) {

View file

@ -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;

View file

@ -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) {

View file

@ -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;

View file

@ -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, '/');
}
/**

View file

@ -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;
}

View file

@ -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.

View file

@ -860,7 +860,7 @@ class App {
),
'Vendor' => array(
'%s' . 'Vendor' . DS,
VENDORS
dirname(dirname(CAKE)) . DS . 'vendors' . DS,
),
'Plugin' => array(
APP . 'Plugin' . DS,

View file

@ -217,6 +217,7 @@ class ErrorHandler {
$log = LOG_NOTICE;
break;
case E_DEPRECATED:
case E_USER_DEPRECATED:
$error = 'Deprecated';
$log = LOG_NOTICE;
break;

View file

@ -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);
}

View file

@ -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) {

View file

@ -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',

View file

@ -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);

View file

@ -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;

View file

@ -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';

View file

@ -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);
}
}

View file

@ -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.
*

View file

@ -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 = <<<SQL
CREATE PROCEDURE cake_test_procedure
AS
BEGIN
RETURN 2;
END
SQL;
$this->Dbo->execute($sql);
$sql = <<<SQL
DECLARE @return_value int
EXEC @return_value = [cake_test_procedure]
SELECT 'value' = @return_value
SQL;
$query = $this->Dbo->execute($sql);
$this->Dbo->execute('DROP PROC cake_test_procedure');
$result = $query->fetch();
$this->assertEquals(2, $result['value']);
}
}

View file

@ -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);
}
/**

View file

@ -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');

View file

@ -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
*

View file

@ -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();
}
}

View file

@ -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!'

View file

@ -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);
}
}
}

View file

@ -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

View file

@ -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'));

View file

@ -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')) {