Merge branch 'master' into 2.6

Conflicts:
	lib/Cake/basics.php
This commit is contained in:
mark_story 2014-08-30 21:28:11 -04:00
commit 7c316bbc56
20 changed files with 266 additions and 23 deletions

View file

@ -271,11 +271,12 @@ class FileEngine extends CacheEngine {
if (substr($entry, 0, $prefixLength) !== $this->settings['prefix']) { if (substr($entry, 0, $prefixLength) !== $this->settings['prefix']) {
continue; continue;
} }
$filePath = $path . $entry;
if (!file_exists($filePath) || is_dir($filePath)) { try {
$file = new SplFileObject($path . $entry, 'r');
} catch (Exception $e) {
continue; continue;
} }
$file = new SplFileObject($path . $entry, 'r');
if ($threshold) { if ($threshold) {
$mtime = $file->getMTime(); $mtime = $file->getMTime();

View file

@ -667,7 +667,8 @@ class I18n {
* @return string Translated string with arguments * @return string Translated string with arguments
*/ */
public static function insertArgs($translated, array $args) { public static function insertArgs($translated, array $args) {
if (empty($args)) { $len = count($args);
if ($len === 0 || ($len === 1 && $args[0] === null)) {
return $translated; return $translated;
} }

View file

@ -267,7 +267,7 @@ class CakeSession {
* @return bool Success * @return bool Success
*/ */
public static function delete($name) { public static function delete($name) {
if (self::check($name)) { if (self::start() && self::check($name)) {
self::_overwrite($_SESSION, Hash::remove($_SESSION, $name)); self::_overwrite($_SESSION, Hash::remove($_SESSION, $name));
return !self::check($name); return !self::check($name);
} }

View file

@ -351,6 +351,9 @@ class Mysql extends DboSource {
if (in_array($fields[$column->Field]['type'], $this->fieldParameters['unsigned']['types'], true)) { if (in_array($fields[$column->Field]['type'], $this->fieldParameters['unsigned']['types'], true)) {
$fields[$column->Field]['unsigned'] = $this->_unsigned($column->Type); $fields[$column->Field]['unsigned'] = $this->_unsigned($column->Type);
} }
if ($fields[$column->Field]['type'] === 'timestamp' && strtoupper($column->Default) === 'CURRENT_TIMESTAMP') {
$fields[$column->Field]['default'] = '';
}
if (!empty($column->Key) && isset($this->index[$column->Key])) { if (!empty($column->Key) && isset($this->index[$column->Key])) {
$fields[$column->Field]['key'] = $this->index[$column->Key]; $fields[$column->Field]['key'] = $this->index[$column->Key];
} }

View file

@ -1113,11 +1113,6 @@ class DboSource extends DataSource {
$filtered = array(); $filtered = array();
// Filter hasOne and belongsTo associations
if ($queryData['callbacks'] === true || $queryData['callbacks'] === 'after') {
$filtered = $this->_filterResults($resultSet, $Model);
}
// Deep associations // Deep associations
if ($Model->recursive > -1) { if ($Model->recursive > -1) {
$joined = array(); $joined = array();
@ -1148,11 +1143,11 @@ class DboSource extends DataSource {
} }
} }
} }
}
if ($queryData['callbacks'] === true || $queryData['callbacks'] === 'after') { if ($queryData['callbacks'] === true || $queryData['callbacks'] === 'after') {
$this->_filterResults($resultSet, $Model, $filtered); $this->_filterResults($resultSet, $Model, $filtered);
} }
}
if ($recursive !== null) { if ($recursive !== null) {
$Model->recursive = $modelRecursive; $Model->recursive = $modelRecursive;

View file

@ -1201,6 +1201,10 @@ class Model extends Object implements CakeEventListener {
continue; continue;
} }
if (!isset($this->data[$modelName])) {
$this->data[$modelName] = array();
}
foreach ($fieldSet as $fieldName => $fieldValue) { foreach ($fieldSet as $fieldName => $fieldValue) {
unset($this->validationErrors[$fieldName]); unset($this->validationErrors[$fieldName]);

View file

@ -371,7 +371,7 @@ class CakeRequest implements ArrayAccess {
protected function _processFileData($path, $data, $field) { protected function _processFileData($path, $data, $field) {
foreach ($data as $key => $fields) { foreach ($data as $key => $fields) {
$newPath = $key; $newPath = $key;
if (!empty($path)) { if (strlen($path) > 0) {
$newPath = $path . '.' . $key; $newPath = $path . '.' . $key;
} }
if (is_array($fields)) { if (is_array($fields)) {

View file

@ -327,8 +327,11 @@ class HttpSocket extends CakeSocket {
} elseif (isset($this->request['auth'], $this->request['auth']['method'], $this->request['auth']['user'], $this->request['auth']['pass'])) { } elseif (isset($this->request['auth'], $this->request['auth']['method'], $this->request['auth']['user'], $this->request['auth']['pass'])) {
$this->configAuth($this->request['auth']['method'], $this->request['auth']['user'], $this->request['auth']['pass']); $this->configAuth($this->request['auth']['method'], $this->request['auth']['user'], $this->request['auth']['pass']);
} }
$authHeader = Hash::get($this->request, 'header.Authorization');
if (empty($authHeader)) {
$this->_setAuth(); $this->_setAuth();
$this->request['auth'] = $this->_auth; $this->request['auth'] = $this->_auth;
}
if (is_array($this->request['body'])) { if (is_array($this->request['body'])) {
$this->request['body'] = http_build_query($this->request['body'], '', '&'); $this->request['body'] = http_build_query($this->request['body'], '', '&');

View file

@ -381,6 +381,14 @@ class BasicsTest extends CakeTestCase {
$expected = 'Some string with multiple arguments'; $expected = 'Some string with multiple arguments';
$this->assertEquals($expected, $result); $this->assertEquals($expected, $result);
$result = __('Some string with %s and a null argument', null);
$expected = 'Some string with %s and a null argument';
$this->assertEquals($expected, $result);
$result = __('Some string with multiple %s%s, first being null', null, 'arguments');
$expected = 'Some string with multiple arguments, first being null';
$this->assertEquals($expected, $result);
$result = __('Some string with %s %s', array('multiple', 'arguments')); $result = __('Some string with %s %s', array('multiple', 'arguments'));
$expected = 'Some string with multiple arguments'; $expected = 'Some string with multiple arguments';
$this->assertEquals($expected, $result); $this->assertEquals($expected, $result);
@ -947,7 +955,7 @@ EXPECTED;
if (php_sapi_name() === 'cli') { if (php_sapi_name() === 'cli') {
$expected = sprintf($expectedText, str_replace(CAKE_CORE_INCLUDE_PATH, '', __FILE__), __LINE__ - 18); $expected = sprintf($expectedText, str_replace(CAKE_CORE_INCLUDE_PATH, '', __FILE__), __LINE__ - 18);
} else { } else {
$expected = sprintf($expectedHtml, str_replace(CAKE_CORE_INCLUDE_PATH, '', __FILE__), __LINE__ - 19); $expected = sprintf($expectedHtml, str_replace(CAKE_CORE_INCLUDE_PATH, '', __FILE__), __LINE__ - 20);
} }
$this->assertEquals($expected, $result); $this->assertEquals($expected, $result);

View file

@ -365,6 +365,12 @@ class CakeSessionTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testDelete() { public function testDelete() {
$this->assertTrue(TestCakeSession::write('Delete.me', 'Clearing out'));
session_write_close();
$this->assertTrue(TestCakeSession::delete('Delete.me'));
$this->assertFalse(TestCakeSession::check('Delete.me'));
$this->assertTrue(TestCakeSession::write('Delete.me', 'Clearing out')); $this->assertTrue(TestCakeSession::write('Delete.me', 'Clearing out'));
$this->assertTrue(TestCakeSession::delete('Delete.me')); $this->assertTrue(TestCakeSession::delete('Delete.me'));
$this->assertFalse(TestCakeSession::check('Delete.me')); $this->assertFalse(TestCakeSession::check('Delete.me'));

View file

@ -884,6 +884,32 @@ class MysqlTest extends CakeTestCase {
$this->assertTrue(isset($result['color'])); $this->assertTrue(isset($result['color']));
} }
/**
* Test that describe() ignores `default current_timestamp` in timestamp columns.
*
* @return void
*/
public function testDescribeHandleCurrentTimestamp() {
$name = $this->Dbo->fullTableName('timestamp_default_values');
$sql = <<<SQL
CREATE TABLE $name (
id INT(11) NOT NULL AUTO_INCREMENT,
phone VARCHAR(10),
limit_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(id)
);
SQL;
$this->Dbo->execute($sql);
$model = new Model(array(
'table' => 'timestamp_default_values',
'ds' => 'test',
'alias' => 'TimestampDefaultValue'
));
$result = $this->Dbo->describe($model);
$this->assertEquals('', $result['limit_date']['default']);
$this->Dbo->execute('DROP TABLE ' . $name);
}
/** /**
* test that a describe() gets additional fieldParameters * test that a describe() gets additional fieldParameters
* *

View file

@ -1508,4 +1508,118 @@ class DboSourceTest extends CakeTestCase {
$this->assertCount(2, $result['Article']['Tag']); $this->assertCount(2, $result['Article']['Tag']);
$this->assertCount(2, $result['Article']['Comment']); $this->assertCount(2, $result['Article']['Comment']);
} }
/**
* Test that afterFind is called correctly for 'joins'
*
* @return void
*/
public function testJoinsAfterFind() {
$this->loadFixtures('Article', 'User');
$User = new User();
$User->bindModel(array('hasOne' => array('Article')));
$Article = $this->getMock('Article', array('afterFind'), array(), '', true);
$Article->expects($this->once())
->method('afterFind')
->with(
array(
0 => array(
'Article' => array(
'id' => '1',
'user_id' => '1',
'title' => 'First Article',
'body' => 'First Article Body',
'published' => 'Y',
'created' => '2007-03-18 10:39:23',
'updated' => '2007-03-18 10:41:31'
)
)
),
$this->isFalse()
)
->will($this->returnArgument(0));
$User->Article = $Article;
$User->find('first', array(
'fields' => array(
'Article.id',
'Article.user_id',
'Article.title',
'Article.body',
'Article.published',
'Article.created',
'Article.updated'
),
'conditions' => array('User.id' => 1),
'recursive' => -1,
'joins' => array(
array(
'table' => 'articles',
'alias' => 'Article',
'type' => 'LEFT',
'conditions' => array(
'Article.user_id = User.id'
),
)
),
'order' => array('Article.id')
));
}
/**
* Test that afterFind is called correctly for 'hasOne' association.
*
* @return void
*/
public function testHasOneAfterFind() {
$this->loadFixtures('Article', 'User', 'Comment');
$User = new User();
$User->bindModel(array('hasOne' => array('Article')));
$Article = $this->getMock('Article', array('afterFind'), array(), '', true);
$Article->unbindModel(array(
'belongsTo' => array('User'),
'hasMany' => array('Comment'),
'hasAndBelongsToMany' => array('Tag')
));
$Article->bindModel(array(
'hasOne' => array('Comment'),
));
$Article->expects($this->once())
->method('afterFind')
->with(
$this->equalTo(
array(
0 => array(
'Article' => array(
'id' => '1',
'user_id' => '1',
'title' => 'First Article',
'body' => 'First Article Body',
'published' => 'Y',
'created' => '2007-03-18 10:39:23',
'updated' => '2007-03-18 10:41:31',
'Comment' => array(
'id' => '1',
'article_id' => '1',
'user_id' => '2',
'comment' => 'First Comment for First Article',
'published' => 'Y',
'created' => '2007-03-18 10:45:23',
'updated' => '2007-03-18 10:47:31',
)
)
)
)
),
$this->isFalse()
)
->will($this->returnArgument(0));
$User->Article = $Article;
$User->find('first', array('conditions' => array('User.id' => 1), 'recursive' => 2));
}
} }

View file

@ -1976,6 +1976,47 @@ class ModelWriteTest extends BaseModelTest {
$this->assertEquals($expected, Hash::extract($result, 'JoinC.{n}.JoinAsJoinC.other')); $this->assertEquals($expected, Hash::extract($result, 'JoinC.{n}.JoinAsJoinC.other'));
} }
/**
* test that saving HABTM with an empty array will clear existing HABTM if
* unique is true
*
* @return void
*/
public function testSaveHabtmEmptyData() {
$this->loadFixtures('Node', 'Dependency');
$Node = new Node();
$data = array(
'Node' => array('name' => 'New First')
);
$Node->id = 1;
$Node->save($data);
$node = $Node->find('first', array(
'conditions' => array('Node.id' => 1),
'contain' => array('ParentNode')
));
$result = Hash::extract($node, 'ParentNode.{n}.id');
$expected = array(2);
$this->assertEquals($expected, $result);
$data = array(
'ParentNode' => array()
);
$Node->id = 1;
$Node->save($data);
$node = $Node->find('first', array(
'conditions' => array('Node.id' => 1),
'contain' => array('ParentNode')
));
$result = Hash::extract($node, 'ParentNode.{n}.id');
$expected = array();
$this->assertEquals($expected, $result);
}
/** /**
* testSaveHabtmNoPrimaryData method * testSaveHabtmNoPrimaryData method
* *

View file

@ -1126,6 +1126,16 @@ class HttpSocketTest extends CakeTestCase {
)); ));
$this->assertEquals($this->Socket->request['auth'], array('Basic' => array('user' => 'joel', 'pass' => 'hunter2'))); $this->assertEquals($this->Socket->request['auth'], array('Basic' => array('user' => 'joel', 'pass' => 'hunter2')));
$this->assertTrue(strpos($this->Socket->request['header'], 'Authorization: Basic am9lbDpodW50ZXIy') !== false); $this->assertTrue(strpos($this->Socket->request['header'], 'Authorization: Basic am9lbDpodW50ZXIy') !== false);
$this->Socket->configAuth('Basic', 'mark', 'password');
$this->Socket->request(array(
'method' => 'GET',
'uri' => 'http://example.com/test',
'header' => array(
'Authorization' => 'OtherAuth Hi.There'
)
));
$this->assertPattern('/Authorization: OtherAuth Hi\.There/m', $this->Socket->request['header']);
} }
/** /**
@ -1142,6 +1152,15 @@ class HttpSocketTest extends CakeTestCase {
$this->Socket->get('/test2'); $this->Socket->get('/test2');
$this->assertTrue(strpos($this->Socket->request['header'], 'Authorization: Basic bWFyazpzZWNyZXQ=') !== false); $this->assertTrue(strpos($this->Socket->request['header'], 'Authorization: Basic bWFyazpzZWNyZXQ=') !== false);
$this->Socket->request(array(
'method' => 'GET',
'uri' => 'http://example.com/test',
'header' => array(
'Authorization' => 'OtherAuth Hi.There'
)
));
$this->assertPattern('/Authorization: OtherAuth Hi\.There/m', $this->Socket->request['header']);
$this->Socket->get('/test3'); $this->Socket->get('/test3');
$this->assertTrue(strpos($this->Socket->request['header'], 'Authorization: Basic bWFyazpzZWNyZXQ=') !== false); $this->assertTrue(strpos($this->Socket->request['header'], 'Authorization: Basic bWFyazpzZWNyZXQ=') !== false);
} }

View file

@ -996,6 +996,23 @@ class RouterTest extends CakeTestCase {
$this->assertEquals('/admin/other/posts/index', $result); $this->assertEquals('/admin/other/posts/index', $result);
} }
/**
* Test that URL's fail to parse when they are prefixed with //
*
* @return void
*/
public function testUrlParseFailureDoubleSlash() {
Router::connect('/posts', array('controller' => 'posts', 'action' => 'index'));
$result = Router::parse('/posts');
$this->assertEquals(
array('pass' => array(), 'named' => array(), 'plugin' => null, 'controller' => 'posts', 'action' => 'index'),
$result
);
$result = Router::parse('//posts');
$this->assertEquals(array(), $result);
}
/** /**
* testUrlParsing method * testUrlParsing method
* *

View file

@ -176,6 +176,7 @@ class InflectorTest extends CakeTestCase {
$this->assertEquals(Inflector::singularize('curves'), 'curve'); $this->assertEquals(Inflector::singularize('curves'), 'curve');
$this->assertEquals(Inflector::singularize('body_curves'), 'body_curve'); $this->assertEquals(Inflector::singularize('body_curves'), 'body_curve');
$this->assertEquals(Inflector::singularize('metadata'), 'metadata'); $this->assertEquals(Inflector::singularize('metadata'), 'metadata');
$this->assertEquals(Inflector::singularize('files_metadata'), 'files_metadata');
$this->assertEquals(Inflector::singularize(''), ''); $this->assertEquals(Inflector::singularize(''), '');
} }
@ -241,6 +242,7 @@ class InflectorTest extends CakeTestCase {
$this->assertEquals(Inflector::pluralize('curve'), 'curves'); $this->assertEquals(Inflector::pluralize('curve'), 'curves');
$this->assertEquals(Inflector::pluralize('body_curve'), 'body_curves'); $this->assertEquals(Inflector::pluralize('body_curve'), 'body_curves');
$this->assertEquals(Inflector::pluralize('metadata'), 'metadata'); $this->assertEquals(Inflector::pluralize('metadata'), 'metadata');
$this->assertEquals(Inflector::pluralize('files_metadata'), 'files_metadata');
$this->assertEquals(Inflector::pluralize('stadia'), 'stadia'); $this->assertEquals(Inflector::pluralize('stadia'), 'stadia');
$this->assertEquals(Inflector::pluralize(''), ''); $this->assertEquals(Inflector::pluralize(''), '');
} }

View file

@ -30,6 +30,7 @@ class DependencyFixture extends CakeTestFixture {
* @var array * @var array
*/ */
public $fields = array( public $fields = array(
'id' => 'integer',
'child_id' => 'integer', 'child_id' => 'integer',
'parent_id' => 'integer' 'parent_id' => 'integer'
); );
@ -40,6 +41,6 @@ class DependencyFixture extends CakeTestFixture {
* @var array * @var array
*/ */
public $records = array( public $records = array(
array('child_id' => 1, 'parent_id' => 2), array('id' => 1, 'child_id' => 1, 'parent_id' => 2),
); );
} }

View file

@ -31,8 +31,8 @@ class TagFixture extends CakeTestFixture {
public $fields = array( public $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary'), 'id' => array('type' => 'integer', 'key' => 'primary'),
'tag' => array('type' => 'string', 'null' => false), 'tag' => array('type' => 'string', 'null' => false),
'created' => 'datetime', 'created' => array('type' => 'datetime', 'null' => true, 'default' => null),
'updated' => 'datetime' 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null),
); );
/** /**

View file

@ -32,7 +32,7 @@ class Inflector {
*/ */
protected static $_plural = array( protected static $_plural = array(
'rules' => array( 'rules' => array(
'/(s)tatus$/i' => '\1\2tatuses', '/(s)tatus$/i' => '\1tatuses',
'/(quiz)$/i' => '\1zes', '/(quiz)$/i' => '\1zes',
'/^(ox)$/i' => '\1\2en', '/^(ox)$/i' => '\1\2en',
'/([m|l])ouse$/i' => '\1ice', '/([m|l])ouse$/i' => '\1ice',
@ -57,6 +57,7 @@ class Inflector {
), ),
'uninflected' => array( 'uninflected' => array(
'.*[nrlm]ese', '.*[nrlm]ese',
'.*data',
'.*deer', '.*deer',
'.*fish', '.*fish',
'.*measles', '.*measles',
@ -152,6 +153,7 @@ class Inflector {
'/s$/i' => '' '/s$/i' => ''
), ),
'uninflected' => array( 'uninflected' => array(
'.*data',
'.*[nrlm]ese', '.*deer', '.*fish', '.*measles', '.*ois', '.*pox', '.*sheep', '.*ss', 'feedback' '.*[nrlm]ese', '.*deer', '.*fish', '.*measles', '.*ois', '.*pox', '.*sheep', '.*ss', 'feedback'
), ),
'irregular' => array( 'irregular' => array(
@ -171,7 +173,7 @@ class Inflector {
'Foochowese', 'gallows', 'Genevese', 'Genoese', 'Gilbertese', 'graffiti', 'Foochowese', 'gallows', 'Genevese', 'Genoese', 'Gilbertese', 'graffiti',
'headquarters', 'herpes', 'hijinks', 'Hottentotese', 'information', 'innings', 'headquarters', 'herpes', 'hijinks', 'Hottentotese', 'information', 'innings',
'jackanapes', 'Kiplingese', 'Kongoese', 'Lucchese', 'mackerel', 'Maltese', '.*?media', 'jackanapes', 'Kiplingese', 'Kongoese', 'Lucchese', 'mackerel', 'Maltese', '.*?media',
'metadata', 'mews', 'moose', 'mumps', 'Nankingese', 'news', 'nexus', 'Niasese', 'mews', 'moose', 'mumps', 'Nankingese', 'news', 'nexus', 'Niasese',
'Pekingese', 'Piedmontese', 'pincers', 'Pistoiese', 'pliers', 'Portuguese', 'Pekingese', 'Piedmontese', 'pincers', 'Pistoiese', 'pliers', 'Portuguese',
'proceedings', 'rabies', 'research', 'rice', 'rhinoceros', 'salmon', 'Sarawakese', 'scissors', 'proceedings', 'rabies', 'research', 'rice', 'rhinoceros', 'salmon', 'Sarawakese', 'scissors',
'sea[- ]bass', 'series', 'Shavese', 'shears', 'siemens', 'species', 'swine', 'testes', 'sea[- ]bass', 'series', 'Shavese', 'shears', 'siemens', 'species', 'swine', 'testes',

View file

@ -120,6 +120,7 @@ class SessionHelper extends AppHelper {
if (CakeSession::check('Message.' . $key)) { if (CakeSession::check('Message.' . $key)) {
$flash = CakeSession::read('Message.' . $key); $flash = CakeSession::read('Message.' . $key);
CakeSession::delete('Message.' . $key);
$message = $flash['message']; $message = $flash['message'];
unset($flash['message']); unset($flash['message']);
@ -144,7 +145,6 @@ class SessionHelper extends AppHelper {
$tmpVars['message'] = $message; $tmpVars['message'] = $message;
$out = $this->_View->element($flash['element'], $tmpVars, $options); $out = $this->_View->element($flash['element'], $tmpVars, $options);
} }
CakeSession::delete('Message.' . $key);
} }
return $out; return $out;
} }