diff --git a/lib/Cake/Console/Command/Task/ExtractTask.php b/lib/Cake/Console/Command/Task/ExtractTask.php index 147a10a6d..fb7102787 100644 --- a/lib/Cake/Console/Command/Task/ExtractTask.php +++ b/lib/Cake/Console/Command/Task/ExtractTask.php @@ -105,6 +105,38 @@ class ExtractTask extends AppShell { */ protected $_validationDomain = 'default'; +/** + * Method to interact with the User and get path selections. + * + * @return void + */ + protected function _getPaths() { + $defaultPath = APP; + while (true) { + $currentPaths = count($this->_paths) > 0 ? $this->_paths : array('None'); + $message = __d( + 'cake_console', + "Current paths: %s\nWhat is the path you would like to extract?\n[Q]uit [D]one", + implode(', ', $currentPaths) + ); + $response = $this->in($message, null, $defaultPath); + if (strtoupper($response) === 'Q') { + $this->out(__d('cake_console', 'Extract Aborted')); + return $this->_stop(); + } elseif (strtoupper($response) === 'D' && count($this->_paths)) { + $this->out(); + return; + } elseif (strtoupper($response) === 'D') { + $this->err(__d('cake_console', 'No directories selected. Please choose a directory.')); + } elseif (is_dir($response)) { + $this->_paths[] = $response; + $defaultPath = 'D'; + } else { + $this->err(__d('cake_console', 'The directory path you supplied was not found. Please try again.')); + } + $this->out(); + } + } /** * Execution method always used for tasks * @@ -127,24 +159,7 @@ class ExtractTask extends AppShell { $this->_paths = array(CakePlugin::path($plugin)); $this->params['plugin'] = $plugin; } else { - $defaultPath = APP; - $message = __d('cake_console', "What is the path you would like to extract?\n[Q]uit [D]one"); - while (true) { - $response = $this->in($message, null, $defaultPath); - if (strtoupper($response) === 'Q') { - $this->out(__d('cake_console', 'Extract Aborted')); - $this->_stop(); - } elseif (strtoupper($response) === 'D') { - $this->out(); - break; - } elseif (is_dir($response)) { - $this->_paths[] = $response; - $defaultPath = 'D'; - } else { - $this->err(__d('cake_console', 'The directory path you supplied was not found. Please try again.')); - } - $this->out(); - } + $this->_getPaths(); } if (!empty($this->params['exclude-plugins']) && $this->_isExtractingApp()) { diff --git a/lib/Cake/Console/Shell.php b/lib/Cake/Console/Shell.php index 788bb8b39..40c8c04ef 100644 --- a/lib/Cake/Console/Shell.php +++ b/lib/Cake/Console/Shell.php @@ -680,12 +680,14 @@ class Shell extends Object { * @return boolean Success */ protected function _checkUnitTest() { - if (App::import('Vendor', 'phpunit', array('file' => 'PHPUnit' . DS . 'Autoload.php'))) { - return true; - } - if (@include 'PHPUnit' . DS . 'Autoload.php') { + if (class_exists('PHPUnit_Framework_TestCase')) { + return true; + } elseif (@include 'PHPUnit' . DS . 'Autoload.php') { + return true; + } elseif (App::import('Vendor', 'phpunit', array('file' => 'PHPUnit' . DS . 'Autoload.php'))) { return true; } + $prompt = __d('cake_console', 'PHPUnit is not installed. Do you want to bake unit test files anyway?'); $unitTest = $this->in($prompt, array('y', 'n'), 'y'); $result = strtolower($unitTest) == 'y' || strtolower($unitTest) == 'yes'; diff --git a/lib/Cake/Model/Model.php b/lib/Cake/Model/Model.php index 9de8f322a..39dca3ed5 100644 --- a/lib/Cake/Model/Model.php +++ b/lib/Cake/Model/Model.php @@ -1138,9 +1138,7 @@ class Model extends Object implements CakeEventListener { if (is_array($one)) { $data = $one; if (empty($one[$this->alias])) { - if ($this->getAssociated(key($one)) === null) { - $data = array($this->alias => $one); - } + $data = $this->_setAliasData($one); } } else { $data = array($this->alias => array($one => $two)); @@ -1169,6 +1167,24 @@ class Model extends Object implements CakeEventListener { return $data; } +/** + * Move values to alias + * + * @param array $data + * @return array + */ + protected function _setAliasData($data) { + $models = array_keys($this->getAssociated()); + $schema = array_keys($this->schema()); + foreach ($data as $field => $value) { + if (in_array($field, $schema) || !in_array($field, $models)) { + $data[$this->alias][$field] = $value; + unset($data[$field]); + } + } + return $data; + } + /** * Normalize Xml::toArray() to use in Model::save() * @@ -2177,6 +2193,7 @@ class Model extends Object implements CakeEventListener { $db = $this->getDataSource(); $transactionBegun = $db->begin(); } + $associations = $this->getAssociated(); $return = array(); $validates = true; diff --git a/lib/Cake/Model/ModelValidator.php b/lib/Cake/Model/ModelValidator.php index be8d15921..7bb95d869 100644 --- a/lib/Cake/Model/ModelValidator.php +++ b/lib/Cake/Model/ModelValidator.php @@ -115,21 +115,14 @@ class ModelValidator implements ArrayAccess, IteratorAggregate, Countable { $model = $this->getModel(); $options = array_merge(array('atomic' => true, 'deep' => false), $options); $model->validationErrors = $validationErrors = $return = array(); - if (!($model->create($data) && $model->validates($options))) { + $model->create(null); + if (!($model->set($data) && $model->validates($options))) { $validationErrors[$model->alias] = $model->validationErrors; $return[$model->alias] = false; } else { $return[$model->alias] = true; } - - if (empty($options['deep'])) { - $data = $model->data; - } else { - $modelData = $model->data; - $recordData = $modelData[$model->alias]; - unset($modelData[$model->alias]); - $data = $modelData + array_merge($data, $recordData); - } + $data = $model->data; $associations = $model->getAssociated(); foreach ($data as $association => &$values) { @@ -200,7 +193,8 @@ class ModelValidator implements ArrayAccess, IteratorAggregate, Countable { if ($options['deep']) { $validates = $model->validateAssociated($record, $options); } else { - $validates = $model->create($record) && $model->validates($options); + $model->create(null); + $validates = $model->set($record) && $model->validates($options); $data[$key] = $model->data; } if ($validates === false || (is_array($validates) && in_array(false, $validates, true))) { diff --git a/lib/Cake/Test/Case/Model/ModelReadTest.php b/lib/Cake/Test/Case/Model/ModelReadTest.php index 5c9bf482e..55ff51080 100644 --- a/lib/Cake/Test/Case/Model/ModelReadTest.php +++ b/lib/Cake/Test/Case/Model/ModelReadTest.php @@ -7868,7 +7868,7 @@ class ModelReadTest extends BaseModelTest { $Article = new CustomArticle(); $data = array('user_id' => 3, 'title' => 'Fourth Article', 'body' => 'Article Body, unpublished', 'published' => 'N'); $Article->create($data); - $Article->save(); + $Article->save(null, false); $this->assertEquals(4, $Article->id); $result = $Article->find('published'); diff --git a/lib/Cake/Test/Case/Model/ModelValidationTest.php b/lib/Cake/Test/Case/Model/ModelValidationTest.php index 021efff8e..530dd96b2 100644 --- a/lib/Cake/Test/Case/Model/ModelValidationTest.php +++ b/lib/Cake/Test/Case/Model/ModelValidationTest.php @@ -1925,21 +1925,32 @@ class ModelValidationTest extends BaseModelTest { $result = $model->saveAll($data, array('validate' => 'first')); $this->assertTrue($result); - $title = $model->field('title', array('body' => 'foo0')); + $this->assertFalse($model->findMethods['unPublished'], 'beforeValidate was run twice'); + + $model->findMethods['unPublished'] = true; + $data = array( + 'CustomArticle' => array( + 'body' => 'foo1' + ) + ); + $result = $model->saveAll($data, array('validate' => 'first', 'deep' => true)); + $this->assertTrue($result); + $title = $model->field('title', array('body' => 'foo1')); $this->assertEquals('foo', $title); + $this->assertFalse($model->findMethods['unPublished'], 'beforeValidate was run twice'); $data = array( - array('body' => 'foo1'), array('body' => 'foo2'), - array('body' => 'foo3') + array('body' => 'foo3'), + array('body' => 'foo4') ); - $result = $model->saveAll($data, array('validate' => 'first')); + $result = $model->saveAll($data, array('validate' => 'first', 'deep' => true)); $this->assertTrue($result); - $this->assertEquals('foo', $model->field('title', array('body' => 'foo1'))); $this->assertEquals('foo', $model->field('title', array('body' => 'foo2'))); $this->assertEquals('foo', $model->field('title', array('body' => 'foo3'))); + $this->assertEquals('foo', $model->field('title', array('body' => 'foo4'))); } /** @@ -1948,7 +1959,7 @@ class ModelValidationTest extends BaseModelTest { * * @return void */ - public function testValidateAssociatedWithBeforeValidate() { + public function testValidateFirstAssociatedWithBeforeValidate() { $this->loadFixtures('Article', 'User'); $model = new CustomArticle(); $model->validate = array( @@ -1978,5 +1989,49 @@ class ModelValidationTest extends BaseModelTest { $this->assertEquals('foo', $model->field('title', array('body' => 'foo3'))); } +/** + * testValidateFirstWithDefaults method + * + * return @void + */ + public function testFirstWithDefaults() { + $this->loadFixtures('Article', 'Tag', 'Comment', 'User', 'ArticlesTag'); + $TestModel = new Article(); + + $result = $TestModel->find('first', array( + 'conditions' => array('Article.id' => 1) + )); + $expected = array( + 'Article' => array( + 'id' => 1, + 'user_id' => 1, + 'title' => 'First Article', + 'body' => 'First Article Body', + 'published' => 'Y', + 'created' => '2007-03-18 10:39:23' + ), + ); + unset($result['Article']['updated']); + $this->assertEquals($expected['Article'], $result['Article']); + + $data = array( + 'Article' => array( + 'id' => 1, + 'title' => 'First Article (modified)' + ), + 'Comment' => array( + array('comment' => 'Article comment', 'user_id' => 1) + ) + ); + $result = $TestModel->saveAll($data, array('validate' => 'first')); + $this->assertTrue($result); + + $result = $TestModel->find('first', array( + 'conditions' => array('Article.id' => 1) + )); + $expected['Article']['title'] = 'First Article (modified)'; + unset($result['Article']['updated']); + $this->assertEquals($expected['Article'], $result['Article']); + } } diff --git a/lib/Cake/Test/Case/Model/ModelWriteTest.php b/lib/Cake/Test/Case/Model/ModelWriteTest.php index a49f8d887..56c431e6d 100644 --- a/lib/Cake/Test/Case/Model/ModelWriteTest.php +++ b/lib/Cake/Test/Case/Model/ModelWriteTest.php @@ -4267,7 +4267,7 @@ class ModelWriteTest extends BaseModelTest { 'author_id' => '3', 'title' => 'Just update the title', 'body' => 'Second Post Body', - 'published' => 'N', + 'published' => 'Y', 'created' => '2007-03-18 10:41:23' )), array( @@ -4356,7 +4356,7 @@ class ModelWriteTest extends BaseModelTest { 'author_id' => '3', 'title' => 'Just update the title', 'body' => 'Second Post Body', - 'published' => 'N', + 'published' => 'Y', 'created' => '2007-03-18 10:41:23' ) ), @@ -4725,7 +4725,7 @@ class ModelWriteTest extends BaseModelTest { 'password' => '5f4dcc3b5aa765d61d8327deb882cf90' ))); - $result = $TestModel->find('all'); + $result = $TestModel->find('all', array('order' => array('Post.id ' => 'ASC'))); $expected = array( 'Post' => array( 'id' => '4', @@ -5623,7 +5623,7 @@ class ModelWriteTest extends BaseModelTest { 'author_id' => '3', 'title' => 'Just update the title', 'body' => 'Second Post Body', - 'published' => 'N', + 'published' => 'Y', 'created' => '2007-03-18 10:41:23' ) ), @@ -5719,7 +5719,7 @@ class ModelWriteTest extends BaseModelTest { 'author_id' => '3', 'title' => 'Just update the title', 'body' => 'Second Post Body', - 'published' => 'N', + 'published' => 'Y', )), array( 'Post' => array( diff --git a/lib/Cake/Test/Case/Model/models.php b/lib/Cake/Test/Case/Model/models.php index fe0db80a2..e9e79a1b6 100644 --- a/lib/Cake/Test/Case/Model/models.php +++ b/lib/Cake/Test/Case/Model/models.php @@ -3119,7 +3119,7 @@ class TranslatedItem2 extends CakeTestModel { /** * translateModel property * - * @var string + * @var string */ public $translateModel = 'TranslateWithPrefix'; @@ -4975,6 +4975,11 @@ class CustomArticle extends AppModel { **/ public function beforeValidate($options = array()) { $this->data[$this->alias]['title'] = 'foo'; + if ($this->findMethods['unPublished'] === true) { + $this->findMethods['unPublished'] = false; + } else { + $this->findMethods['unPublished'] = 'true again'; + } } } diff --git a/lib/Cake/Test/Case/Utility/DebuggerTest.php b/lib/Cake/Test/Case/Utility/DebuggerTest.php index 7285b6924..f45f19cdc 100644 --- a/lib/Cake/Test/Case/Utility/DebuggerTest.php +++ b/lib/Cake/Test/Case/Utility/DebuggerTest.php @@ -140,8 +140,8 @@ class DebuggerTest extends CakeTestCase { 'a' => array( 'href' => "javascript:void(0);", 'onclick' => "preg:/document\.getElementById\('cakeErr[a-z0-9]+\-trace'\)\.style\.display = " . - "\(document\.getElementById\('cakeErr[a-z0-9]+\-trace'\)\.style\.display == 'none'" . - " \? '' \: 'none'\);/" + "\(document\.getElementById\('cakeErr[a-z0-9]+\-trace'\)\.style\.display == 'none'" . + " \? '' \: 'none'\);/" ), 'b' => array(), 'Notice', '/b', ' (8)', )); @@ -149,6 +149,7 @@ class DebuggerTest extends CakeTestCase { $this->assertRegExp('/Undefined variable:\s+buzz/', $result[1]); $this->assertRegExp('/]+>Code/', $result[1]); $this->assertRegExp('/]+>Context/', $result[2]); + $this->assertContains('$wrong = ''', $result[3], 'Context should be HTML escaped.'); } /** @@ -162,14 +163,14 @@ class DebuggerTest extends CakeTestCase { Debugger::output('js', array( 'traceLine' => '{:reference} - {:path}, line {:line}' + '&line={:line}">{:path}, line {:line}' )); $result = Debugger::trace(); $this->assertRegExp('/' . preg_quote('txmt://open?url=file://', '/') . '(\/|[A-Z]:\\\\)' . '/', $result); Debugger::output('xml', array( 'error' => '{:code}{:file}{:line}' . - '{:description}', + '{:description}', 'context' => "{:context}", 'trace' => "{:trace}", )); @@ -361,10 +362,10 @@ TEXT; $this->assertRegExp('/DebuggerTest\:\:testLog/i', $result); $this->assertRegExp("/'cool'/", $result); - unlink(TMP . 'logs' . DS . 'debug.log'); + unlink(LOGS . 'debug.log'); Debugger::log(array('whatever', 'here')); - $result = file_get_contents(TMP . 'logs' . DS . 'debug.log'); + $result = file_get_contents(LOGS . 'debug.log'); $this->assertRegExp('/DebuggerTest\:\:testLog/i', $result); $this->assertRegExp('/\[main\]/', $result); $this->assertRegExp('/array/', $result); diff --git a/lib/Cake/Test/Case/View/Helper/CacheHelperTest.php b/lib/Cake/Test/Case/View/Helper/CacheHelperTest.php index cce3ca21b..f6e04b6a4 100644 --- a/lib/Cake/Test/Case/View/Helper/CacheHelperTest.php +++ b/lib/Cake/Test/Case/View/Helper/CacheHelperTest.php @@ -291,15 +291,14 @@ class CacheHelperTest extends CakeTestCase { */ public function testCacheViewVars() { $this->Controller->cache_parsing(); - $this->Controller->params = array( + $this->Controller->request->addParams(array( 'controller' => 'cache_test', 'action' => 'cache_parsing', 'pass' => array(), 'named' => array() - ); + )); + $this->Controller->request->here = '/cacheTest/cache_parsing'; $this->Controller->cacheAction = 21600; - $this->Controller->here = '/cacheTest/cache_parsing'; - $this->Controller->action = 'cache_parsing'; $View = new View($this->Controller); $result = $View->render('index'); @@ -323,21 +322,20 @@ class CacheHelperTest extends CakeTestCase { * @return void */ public function testCacheCallbacks() { - $this->Controller->cache_parsing(); - $this->Controller->params = array( + $this->Controller->request->addParams(array( 'controller' => 'cache_test', 'action' => 'cache_parsing', 'pass' => array(), 'named' => array() - ); + )); $this->Controller->cacheAction = array( 'cache_parsing' => array( 'duration' => 21600, 'callbacks' => true ) ); - $this->Controller->here = '/cacheTest/cache_parsing'; - $this->Controller->action = 'cache_parsing'; + $this->Controller->request->here = '/cacheTest/cache_parsing'; + $this->Controller->cache_parsing(); $View = new View($this->Controller); $result = $View->render('index'); @@ -358,18 +356,18 @@ class CacheHelperTest extends CakeTestCase { * @return void */ public function testCacheActionArray() { - $this->Controller->cache_parsing(); $this->Controller->request->addParams(array( 'controller' => 'cache_test', 'action' => 'cache_parsing', 'pass' => array(), 'named' => array() )); + $this->Controller->request->here = '/cache_test/cache_parsing'; $this->Controller->cacheAction = array( 'cache_parsing' => 21600 ); - $this->Controller->request->here = '/cache_test/cache_parsing'; - $this->Controller->action = 'cache_parsing'; + + $this->Controller->cache_parsing(); $View = new View($this->Controller); $result = $View->render('index'); @@ -380,13 +378,25 @@ class CacheHelperTest extends CakeTestCase { $filename = CACHE . 'views' . DS . 'cache_test_cache_parsing.php'; $this->assertTrue(file_exists($filename)); @unlink($filename); + } - $this->Controller->cache_parsing(); +/** + * Test that cacheAction works with camelcased controller names. + * + * @return void + */ + public function testCacheActionArrayCamelCase() { + $this->Controller->request->addParams(array( + 'controller' => 'cache_test', + 'action' => 'cache_parsing', + 'pass' => array(), + 'named' => array() + )); $this->Controller->cacheAction = array( 'cache_parsing' => 21600 ); $this->Controller->request->here = '/cacheTest/cache_parsing'; - $this->Controller->action = 'cache_parsing'; + $this->Controller->cache_parsing(); $View = new View($this->Controller); $result = $View->render('index'); @@ -397,28 +407,6 @@ class CacheHelperTest extends CakeTestCase { $filename = CACHE . 'views' . DS . 'cachetest_cache_parsing.php'; $this->assertTrue(file_exists($filename)); @unlink($filename); - - $this->Controller->cache_parsing(); - $this->Controller->request->addParams(array( - 'controller' => 'cache_test', - 'action' => 'cache_parsing', - 'pass' => array(), - 'named' => array() - )); - $this->Controller->cacheAction = array( - 'some_other_action' => 21600 - ); - $this->Controller->request->here = '/cacheTest/cache_parsing'; - $this->Controller->action = 'cache_parsing'; - - $View = new View($this->Controller); - $result = $View->render('index'); - - $this->assertNotRegExp('/cake:nocache/', $result); - $this->assertNotRegExp('/php echo/', $result); - - $filename = CACHE . 'views' . DS . 'cachetest_cache_parsing.php'; - $this->assertFalse(file_exists($filename)); } /** diff --git a/lib/Cake/Utility/Debugger.php b/lib/Cake/Utility/Debugger.php index d503fc2f5..5d7b1c43a 100644 --- a/lib/Cake/Utility/Debugger.php +++ b/lib/Cake/Utility/Debugger.php @@ -63,11 +63,13 @@ class Debugger { 'trace' => '
{:trace}
', 'code' => '', 'context' => '', - 'links' => array() + 'links' => array(), + 'escapeContext' => true, ), 'html' => array( 'trace' => '
Trace 

{:trace}

', - 'context' => '
Context 

{:context}

' + 'context' => '
Context 

{:context}

', + 'escapeContext' => true, ), 'txt' => array( 'error' => "{:error}: {:code} :: {:description} on line {:line} of {:path}\n{:info}", @@ -716,7 +718,7 @@ class Debugger { $info = ''; foreach ((array)$data['context'] as $var => $value) { - $context[] = "\${$var}\t=\t" . $this->exportVar($value, 1); + $context[] = "\${$var} = " . $this->exportVar($value, 1); } switch ($this->_outputFormat) { @@ -731,30 +733,29 @@ class Debugger { $data['trace'] = $trace; $data['id'] = 'cakeErr' . uniqid(); $tpl = array_merge($this->_templates['base'], $this->_templates[$this->_outputFormat]); - $insert = array('context' => join("\n", $context)) + $data; - - $detect = array('context'); if (isset($tpl['links'])) { foreach ($tpl['links'] as $key => $val) { - if (in_array($key, $detect) && empty($insert[$key])) { - continue; - } - $links[$key] = String::insert($val, $insert, $insertOpts); + $links[$key] = String::insert($val, $data, $insertOpts); } } - foreach (array('code', 'context', 'trace') as $key) { - if (empty($$key) || !isset($tpl[$key])) { + if (!empty($tpl['escapeContext'])) { + $context = h($context); + } + + $infoData = compact('code', 'context', 'trace'); + foreach ($infoData as $key => $value) { + if (empty($value) || !isset($tpl[$key])) { continue; } - if (is_array($$key)) { - $$key = join("\n", $$key); + if (is_array($value)) { + $value = join("\n", $value); } - $info .= String::insert($tpl[$key], compact($key) + $insert, $insertOpts); + $info .= String::insert($tpl[$key], array($key => $value) + $data, $insertOpts); } $links = join(' ', $links); - unset($data['context']); + if (isset($tpl['callback']) && is_callable($tpl['callback'])) { return call_user_func($tpl['callback'], $data, compact('links', 'info')); } diff --git a/lib/Cake/View/View.php b/lib/Cake/View/View.php index 79eb24ca4..9db838418 100644 --- a/lib/Cake/View/View.php +++ b/lib/Cake/View/View.php @@ -332,8 +332,10 @@ class View extends Object { * @return CakeEventManager */ public function getEventManager() { - if (empty($this->_eventManager) || !$this->_eventManagerConfigured) { + if (empty($this->_eventManager)) { $this->_eventManager = new CakeEventManager(); + } + if (!$this->_eventManagerConfigured) { $this->_eventManager->attach($this->Helpers); $this->_eventManagerConfigured = true; }