diff --git a/lib/Cake/Controller/Controller.php b/lib/Cake/Controller/Controller.php index 978dade84..8b3098998 100644 --- a/lib/Cake/Controller/Controller.php +++ b/lib/Cake/Controller/Controller.php @@ -796,7 +796,7 @@ class Controller extends Object implements CakeEventListener { * @return array Array with keys url, status and exit */ protected function _parseBeforeRedirect($response, $url, $status, $exit) { - if (is_array($response) && isset($response[0])) { + if (is_array($response) && array_key_exists(0, $response)) { foreach ($response as $resp) { if (is_array($resp) && isset($resp['url'])) { extract($resp, EXTR_OVERWRITE); diff --git a/lib/Cake/Model/Behavior/ContainableBehavior.php b/lib/Cake/Model/Behavior/ContainableBehavior.php index 98989b64a..92df83695 100644 --- a/lib/Cake/Model/Behavior/ContainableBehavior.php +++ b/lib/Cake/Model/Behavior/ContainableBehavior.php @@ -92,21 +92,25 @@ class ContainableBehavior extends ModelBehavior { */ public function beforeFind(Model $Model, $query) { $reset = (isset($query['reset']) ? $query['reset'] : true); - $noContain = ( - (isset($this->runtime[$Model->alias]['contain']) && empty($this->runtime[$Model->alias]['contain'])) || - (isset($query['contain']) && empty($query['contain'])) - ); + $noContain = false; $contain = array(); + if (isset($this->runtime[$Model->alias]['contain'])) { + $noContain = empty($this->runtime[$Model->alias]['contain']); $contain = $this->runtime[$Model->alias]['contain']; unset($this->runtime[$Model->alias]['contain']); } + if (isset($query['contain'])) { - $contain = array_merge($contain, (array)$query['contain']); + $noContain = $noContain || empty($query['contain']); + if ($query['contain'] !== false) { + $contain = array_merge($contain, (array)$query['contain']); + } } + $noContain = $noContain && empty($contain); + if ( - $noContain || !$contain || in_array($contain, array(null, false), true) || - (isset($contain[0]) && $contain[0] === null) + $noContain || empty($contain) || (isset($contain[0]) && $contain[0] === null) ) { if ($noContain) { $query['recursive'] = -1; diff --git a/lib/Cake/Model/Model.php b/lib/Cake/Model/Model.php index 8dcdf3b9b..9f9e63bac 100644 --- a/lib/Cake/Model/Model.php +++ b/lib/Cake/Model/Model.php @@ -2194,7 +2194,7 @@ class Model extends Object implements CakeEventListener { if ($options['validate'] === 'first') { $validates = $this->validateAssociated($data, $options); - if ((!$validates && $options['atomic']) || (!$options['atomic'] && in_array(false, $validates, true))) { + if ((!$validates && $options['atomic']) || (!$options['atomic'] && in_array(false, Hash::flatten($validates), true))) { return $validates; } $options['validate'] = false; diff --git a/lib/Cake/Test/Case/Model/Behavior/ContainableBehaviorTest.php b/lib/Cake/Test/Case/Model/Behavior/ContainableBehaviorTest.php index 0051e93a6..3c6367058 100644 --- a/lib/Cake/Test/Case/Model/Behavior/ContainableBehaviorTest.php +++ b/lib/Cake/Test/Case/Model/Behavior/ContainableBehaviorTest.php @@ -285,6 +285,19 @@ class ContainableBehaviorTest extends CakeTestCase { $this->assertEquals($expected, $result); } +/** + * Test that mixing contain() and the contain find option. + * + * @return void + */ + public function testContainAndContainOption() { + $this->Article->contain(); + $r = $this->Article->find('all', array( + 'contain' => array('Comment') + )); + $this->assertTrue(isset($r[0]['Comment']), 'No comment returned'); + } + /** * testFindEmbeddedNoBindings method * diff --git a/lib/Cake/Test/Case/Model/ModelWriteTest.php b/lib/Cake/Test/Case/Model/ModelWriteTest.php index 31327e7de..d317f6ca9 100644 --- a/lib/Cake/Test/Case/Model/ModelWriteTest.php +++ b/lib/Cake/Test/Case/Model/ModelWriteTest.php @@ -4830,6 +4830,51 @@ class ModelWriteTest extends BaseModelTest { $this->assertEquals($expected, $result[6]['Attachment']); } +/** + * Test that validate = first, atomic = false works when associated records + * fail validation. + * + * @return void + */ + public function testSaveAssociatedAtomicFalseValidateFirstWithErrors() { + $this->loadFixtures('Comment', 'Article', 'User'); + $Article = ClassRegistry::init('Article'); + $Article->Comment->validator()->add('comment', array( + array('rule' => 'notEmpty') + )); + + $data = array( + 'Article' => array( + 'user_id' => 1, + 'title' => 'Foo', + 'body' => 'text', + 'published' => 'N' + ), + 'Comment' => array( + array( + 'user_id' => 1, + 'comment' => '', + 'published' => 'N', + ) + ), + ); + + $Article->saveAssociated( + $data, + array('validate' => 'first', 'atomic' => false) + ); + + $result = $Article->validationErrors; + $expected = array( + 'Comment' => array( + array( + 'comment' => array( 'This field cannot be left blank' ) + ) + ) + ); + $this->assertEquals($expected, $result); + } + /** * testSaveMany method * diff --git a/lib/Cake/Test/Case/Utility/CakeTimeTest.php b/lib/Cake/Test/Case/Utility/CakeTimeTest.php index 04b1b3cde..7185ef00f 100644 --- a/lib/Cake/Test/Case/Utility/CakeTimeTest.php +++ b/lib/Cake/Test/Case/Utility/CakeTimeTest.php @@ -779,17 +779,17 @@ class CakeTimeTest extends CakeTestCase { $expected = time(); $result = $this->Time->fromString(time(), $yourTimezone); - $this->assertEquals($expected, $result); + $this->assertWithinMargin($expected, $result, 1); $result = $this->Time->fromString(time(), $timezoneServer->getName()); - $this->assertEquals($expected, $result); + $this->assertWithinMargin($expected, $result, 1); $result = $this->Time->fromString(time(), $timezoneServer); - $this->assertEquals($expected, $result); + $this->assertWithinMargin($expected, $result, 1); Configure::write('Config.timezone', $timezoneServer->getName()); $result = $this->Time->fromString(time()); - $this->assertEquals($expected, $result); + $this->assertWithinMargin($expected, $result, 1); Configure::delete('Config.timezone'); } @@ -807,17 +807,17 @@ class CakeTimeTest extends CakeTestCase { $result = $this->Time->fromString('+1 hour'); $expected = strtotime('+1 hour'); - $this->assertEquals($expected, $result); + $this->assertWithinMargin($expected, $result, 1); $timezone = date('Z', time()); $result = $this->Time->fromString('+1 hour', $timezone); $expected = $this->Time->convert(strtotime('+1 hour'), $timezone); - $this->assertEquals($expected, $result); + $this->assertWithinMargin($expected, $result, 1); $timezone = date_default_timezone_get(); $result = $this->Time->fromString('+1 hour', $timezone); $expected = $this->Time->convert(strtotime('+1 hour'), $timezone); - $this->assertEquals($expected, $result); + $this->assertWithinMargin($expected, $result, 1); date_default_timezone_set('UTC'); $date = new DateTime('now', new DateTimeZone('Europe/London')); @@ -840,7 +840,7 @@ class CakeTimeTest extends CakeTestCase { $date->setTimezone(new DateTimeZone('UTC')); $expected = $date->format('U') + $date->getOffset(); - $this->assertEquals($expected, $result); + $this->assertWithinMargin($expected, $result, 1); date_default_timezone_set('Australia/Melbourne'); @@ -848,7 +848,7 @@ class CakeTimeTest extends CakeTestCase { $result = $this->Time->fromString($date, 'Asia/Kuwait'); $date->setTimezone(new DateTimeZone('Asia/Kuwait')); $expected = $date->format('U') + $date->getOffset(); - $this->assertEquals($expected, $result); + $this->assertWithinMargin($expected, $result, 1); $this->_restoreSystemTimezone(); } @@ -1058,10 +1058,10 @@ class CakeTimeTest extends CakeTestCase { public function testCorrectTimezoneConversion() { date_default_timezone_set('UTC'); $date = '2012-01-01 10:00:00'; - $converted = CakeTime::format($date, '%Y-%m-%d %H:%M:%S', '', 'Europe/Copenhagen'); + $converted = CakeTime::format($date, '%Y-%m-%d %H:%M', '', 'Europe/Copenhagen'); $expected = new DateTime($date); $expected->setTimezone(new DateTimeZone('Europe/Copenhagen')); - $this->assertEquals($expected->format('Y-m-d H:i:s'), $converted); + $this->assertEquals($expected->format('Y-m-d H:i'), $converted); } }