Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'master' into 2.3

Conflicts:
	lib/Cake/Console/Command/Task/ModelTask.php
	lib/Cake/Model/Model.php
  • Loading branch information...
commit 4af60391079eb7a89f494ffd25a22b5e19a1828b 2 parents 1fc9641 + ce7f85a
@markstory markstory authored
Showing with 202 additions and 54 deletions.
  1. +10 −0 lib/Cake/Console/Command/Task/ControllerTask.php
  2. +1 −1  lib/Cake/Console/Command/Task/DbConfigTask.php
  3. +8 −12 lib/Cake/Console/Command/Task/ModelTask.php
  4. +4 −2 lib/Cake/Console/Command/Task/PluginTask.php
  5. +2 −1  lib/Cake/Controller/Component/CookieComponent.php
  6. +3 −2 lib/Cake/Model/Datasource/CakeSession.php
  7. +3 −1 lib/Cake/Model/Datasource/DboSource.php
  8. +3 −3 lib/Cake/Model/Model.php
  9. +6 −1 lib/Cake/Network/CakeRequest.php
  10. +38 −20 lib/Cake/Test/Case/Console/Command/Task/ControllerTaskTest.php
  11. +1 −1  lib/Cake/Test/Case/Controller/Component/SessionComponentTest.php
  12. +20 −0 lib/Cake/Test/Case/Model/ModelDeleteTest.php
  13. +24 −0 lib/Cake/Test/Case/Model/ModelReadTest.php
  14. +10 −0 lib/Cake/Test/Case/Model/models.php
  15. +8 −0 lib/Cake/Test/Case/Network/CakeRequestTest.php
  16. +6 −0 lib/Cake/Test/Case/Utility/CakeTimeTest.php
  17. +11 −0 lib/Cake/Test/Case/Utility/HashTest.php
  18. +28 −0 lib/Cake/Test/Case/View/Helper/FormHelperTest.php
  19. +1 −1  lib/Cake/Utility/CakeTime.php
  20. +2 −2 lib/Cake/Utility/Hash.php
  21. +1 −1  lib/Cake/Utility/Xml.php
  22. +9 −3 lib/Cake/View/Helper/FormHelper.php
  23. +3 −3 lib/Cake/View/Helper/HtmlHelper.php
View
10 lib/Cake/Console/Command/Task/ControllerTask.php
@@ -105,12 +105,22 @@ public function all() {
$this->listAll($this->connection, false);
ClassRegistry::config('Model', array('ds' => $this->connection));
$unitTestExists = $this->_checkUnitTest();
+
+ $admin = false;
+ if (!empty($this->params['admin'])) {
+ $admin = $this->Project->getPrefix();
+ }
+
foreach ($this->__tables as $table) {
$model = $this->_modelName($table);
$controller = $this->_controllerName($model);
App::uses($model, 'Model');
if (class_exists($model)) {
$actions = $this->bakeActions($controller);
+ if ($admin) {
+ $this->out(__d('cake_console', 'Adding %s methods', $admin));
+ $actions .= "\n" . $this->bakeActions($controller, $admin);
+ }
if ($this->bake($controller, $actions) && $unitTestExists) {
$this->bakeTest($controller);
}
View
2  lib/Cake/Console/Command/Task/DbConfigTask.php
@@ -211,7 +211,7 @@ protected function _verify($config) {
$this->out(__d('cake_console', 'The following database configuration will be created:'));
$this->hr();
$this->out(__d('cake_console', "Name: %s", $name));
- $this->out(__d('cake_console', "Datasource: %s", $datasource));
+ $this->out(__d('cake_console', "Datasource: %s", $datasource));
$this->out(__d('cake_console', "Persistent: %s", $persistent));
$this->out(__d('cake_console', "Host: %s", $host));
View
20 lib/Cake/Console/Command/Task/ModelTask.php
@@ -619,21 +619,17 @@ public function findHasOneAndMany(Model $model, $associations) {
public function findHasAndBelongsToMany(Model $model, $associations) {
$foreignKey = $this->_modelKey($model->name);
foreach ($this->_tables as $otherTable) {
+ $tableName = null;
$offset = strpos($otherTable, $model->table . '_');
$otherOffset = strpos($otherTable, '_' . $model->table);
- if ($offset !== false) {
- $offset = strlen($model->table . '_');
- $habtmName = $this->_modelName(substr($otherTable, $offset));
- $associations['hasAndBelongsToMany'][] = array(
- 'alias' => $habtmName,
- 'className' => $habtmName,
- 'foreignKey' => $foreignKey,
- 'associationForeignKey' => $this->_modelKey($habtmName),
- 'joinTable' => $otherTable
- );
- } elseif ($otherOffset !== false) {
- $habtmName = $this->_modelName(substr($otherTable, 0, $otherOffset));
+ if ($offset === 0) {
+ $tableName = substr($otherTable, strlen($model->table . '_'));
+ } elseif ($otherOffset === 0) {
+ $tableName = substr($otherTable, 0, $otherOffset);
+ }
+ if ($tableName && in_array($tableName, $this->_tables)) {
+ $habtmName = $this->_modelName($tableName);
$associations['hasAndBelongsToMany'][] = array(
'alias' => $habtmName,
'className' => $habtmName,
View
6 lib/Cake/Console/Command/Task/PluginTask.php
@@ -145,15 +145,17 @@ public function bake($plugin) {
$controllerFileName = $plugin . 'AppController.php';
$out = "<?php\n\n";
+ $out .= "App::uses('AppController', 'Controller');\n\n";
$out .= "class {$plugin}AppController extends AppController {\n\n";
- $out .= "}\n\n";
+ $out .= "}\n";
$this->createFile($this->path . $plugin . DS . 'Controller' . DS . $controllerFileName, $out);
$modelFileName = $plugin . 'AppModel.php';
$out = "<?php\n\n";
+ $out .= "App::uses('AppModel', 'Model');\n\n";
$out .= "class {$plugin}AppModel extends AppModel {\n\n";
- $out .= "}\n\n";
+ $out .= "}\n";
$this->createFile($this->path . $plugin . DS . 'Model' . DS . $modelFileName, $out);
$this->_modifyBootstrap($plugin);
View
3  lib/Cake/Controller/Component/CookieComponent.php
@@ -208,7 +208,8 @@ public function startup(Controller $controller) {
* @param string|array $key Key for the value
* @param mixed $value Value
* @param boolean $encrypt Set to true to encrypt value, false otherwise
- * @param integer|string $expires Can be either Unix timestamp, or date string
+ * @param integer|string $expires Can be either the number of seconds until a cookie
+ * expires, or a strtotime compatible time offset.
* @return void
* @link http://book.cakephp.org/2.0/en/core-libraries/components/cookie.html#CookieComponent::write
*/
View
5 lib/Cake/Model/Datasource/CakeSession.php
@@ -419,9 +419,10 @@ public static function write($name, $value = null) {
* @return void
*/
public static function destroy() {
- if (self::started()) {
- session_destroy();
+ if (!self::started()) {
+ self::start();
}
+ session_destroy();
self::clear();
}
View
4 lib/Cake/Model/Datasource/DboSource.php
@@ -1153,10 +1153,12 @@ protected function _filterResults(&$results, Model $model, $filtered = array())
}
$linkedModel = $model->{$className};
$filtering[] = $className;
- foreach ($results as &$result) {
+ foreach ($results as $key => &$result) {
$data = $linkedModel->afterFind(array(array($className => $result[$className])), false);
if (isset($data[0][$className])) {
$result[$className] = $data[0][$className];
+ } else {
+ unset($results[$key]);
}
}
}
View
6 lib/Cake/Model/Model.php
@@ -988,7 +988,7 @@ protected function _createLinks() {
$plugin = null;
if (is_numeric($assoc)) {
- unset ($this->{$type}[$assoc]);
+ unset($this->{$type}[$assoc]);
$assoc = $value;
$value = array();
@@ -1164,7 +1164,7 @@ public function set($one, $two = null) {
foreach ($fieldSet as $fieldName => $fieldValue) {
if (isset($this->validationErrors[$fieldName])) {
- unset ($this->validationErrors[$fieldName]);
+ unset($this->validationErrors[$fieldName]);
}
if ($modelName === $this->alias) {
@@ -2525,7 +2525,7 @@ public function deleteAll($conditions, $cascade = true, $callbacks = false) {
'fields' => "{$this->alias}.{$this->primaryKey}",
'recursive' => 0), compact('conditions'))
);
- if ($ids === false) {
+ if ($ids === false || $ids === null) {
return false;
}
View
7 lib/Cake/Network/CakeRequest.php
@@ -232,7 +232,12 @@ protected function _url() {
} elseif (isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], '://') === false) {
$uri = $_SERVER['REQUEST_URI'];
} elseif (isset($_SERVER['REQUEST_URI'])) {
- $uri = substr($_SERVER['REQUEST_URI'], strlen(FULL_BASE_URL));
+ $qPosition = strpos($_SERVER['REQUEST_URI'], '?');
+ if ($qPosition !== false && strpos($_SERVER['REQUEST_URI'], '://') > $qPosition) {
+ $uri = $_SERVER['REQUEST_URI'];
+ } else {
+ $uri = substr($_SERVER['REQUEST_URI'], strlen(FULL_BASE_URL));
+ }
} elseif (isset($_SERVER['PHP_SELF']) && isset($_SERVER['SCRIPT_NAME'])) {
$uri = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['PHP_SELF']);
} elseif (isset($_SERVER['HTTP_X_REWRITE_URL'])) {
View
58 lib/Cake/Test/Case/Console/Command/Task/ControllerTaskTest.php
@@ -90,6 +90,10 @@ public function setUp() {
array($out, $out, $in)
);
$this->Task->Test = $this->getMock('TestTask', array(), array($out, $out, $in));
+
+ if (!defined('ARTICLE_MODEL_CREATED')) {
+ $this->markTestSkipped('Could not run as an Article, Tag or Comment model was already loaded.');
+ }
}
/**
@@ -340,7 +344,6 @@ public function testBakeWithPlugin() {
* @return void
*/
public function testBakeActionsUsingSessions() {
- $this->skipIf(!defined('ARTICLE_MODEL_CREATED'), 'Testing bakeActions requires Article, Comment & Tag Model to be undefined.');
$result = $this->Task->bakeActions('BakeArticles', null, true);
@@ -380,7 +383,6 @@ public function testBakeActionsUsingSessions() {
* @return void
*/
public function testBakeActionsWithNoSessions() {
- $this->skipIf(!defined('ARTICLE_MODEL_CREATED'), 'Testing bakeActions requires Article, Tag, Comment Models to be undefined.');
$result = $this->Task->bakeActions('BakeArticles', null, false);
@@ -513,9 +515,7 @@ public function testExecuteIntoAll() {
if ($count != count($this->fixtures)) {
$this->markTestSkipped('Additional tables detected.');
}
- if (!defined('ARTICLE_MODEL_CREATED')) {
- $this->markTestSkipped('Execute into all could not be run as an Article, Tag or Comment model was already loaded.');
- }
+
$this->Task->connection = 'test';
$this->Task->path = '/my/path/';
$this->Task->args = array('all');
@@ -533,14 +533,44 @@ public function testExecuteIntoAll() {
}
/**
+ * Test execute() with all and --admin
+ *
+ * @return void
+ */
+ public function testExecuteIntoAllAdmin() {
+ $count = count($this->Task->listAll('test'));
+ if ($count != count($this->fixtures)) {
+ $this->markTestSkipped('Additional tables detected.');
+ }
+
+ $this->Task->connection = 'test';
+ $this->Task->path = '/my/path/';
+ $this->Task->args = array('all');
+ $this->Task->params['admin'] = true;
+
+ $this->Task->Project->expects($this->any())
+ ->method('getPrefix')
+ ->will($this->returnValue('admin_'));
+ $this->Task->expects($this->any())
+ ->method('_checkUnitTest')
+ ->will($this->returnValue(true));
+ $this->Task->Test->expects($this->once())->method('bake');
+
+ $filename = '/my/path/BakeArticlesController.php';
+ $this->Task->expects($this->once())->method('createFile')->with(
+ $filename,
+ $this->stringContains('function admin_index')
+ )->will($this->returnValue(true));
+
+ $this->Task->execute();
+ }
+
+/**
* test that `cake bake controller foos` works.
*
* @return void
*/
public function testExecuteWithController() {
- if (!defined('ARTICLE_MODEL_CREATED')) {
- $this->markTestSkipped('Execute with scaffold param requires no Article, Tag or Comment model to be defined');
- }
$this->Task->connection = 'test';
$this->Task->path = '/my/path/';
$this->Task->args = array('BakeArticles');
@@ -572,9 +602,6 @@ public static function nameVariations() {
* @return void
*/
public function testExecuteWithControllerNameVariations($name) {
- if (!defined('ARTICLE_MODEL_CREATED')) {
- $this->markTestSkipped('Execute with scaffold param requires no Article, Tag or Comment model to be defined.');
- }
$this->Task->connection = 'test';
$this->Task->path = '/my/path/';
$this->Task->args = array($name);
@@ -592,9 +619,6 @@ public function testExecuteWithControllerNameVariations($name) {
* @return void
*/
public function testExecuteWithPublicParam() {
- if (!defined('ARTICLE_MODEL_CREATED')) {
- $this->markTestSkipped('Execute with public param requires no Article, Tag or Comment model to be defined.');
- }
$this->Task->connection = 'test';
$this->Task->path = '/my/path/';
$this->Task->args = array('BakeArticles');
@@ -614,9 +638,6 @@ public function testExecuteWithPublicParam() {
* @return void
*/
public function testExecuteWithControllerAndBoth() {
- if (!defined('ARTICLE_MODEL_CREATED')) {
- $this->markTestSkipped('Execute with controller and both requires no Article, Tag or Comment model to be defined.');
- }
$this->Task->Project->expects($this->any())->method('getPrefix')->will($this->returnValue('admin_'));
$this->Task->connection = 'test';
$this->Task->path = '/my/path/';
@@ -636,9 +657,6 @@ public function testExecuteWithControllerAndBoth() {
* @return void
*/
public function testExecuteWithControllerAndAdmin() {
- if (!defined('ARTICLE_MODEL_CREATED')) {
- $this->markTestSkipped('Execute with controller and admin requires no Article, Tag or Comment model to be defined.');
- }
$this->Task->Project->expects($this->any())->method('getPrefix')->will($this->returnValue('admin_'));
$this->Task->connection = 'test';
$this->Task->path = '/my/path/';
View
2  lib/Cake/Test/Case/Controller/Component/SessionComponentTest.php
@@ -205,7 +205,7 @@ public function testSessionReadWrite() {
$this->assertEquals($Session->read('Test'), $array);
$Session->delete('Test');
- $this->assertFalse($Session->write(array('Test'), 'some value'));
+ $this->assertTrue($Session->write(array('Test'), 'some value'));
$this->assertTrue($Session->write(array('Test' => 'some value')));
$this->assertEquals('some value', $Session->read('Test'));
$Session->delete('Test');
View
20 lib/Cake/Test/Case/Model/ModelDeleteTest.php
@@ -435,6 +435,26 @@ public function testDeleteAllUnknownColumn() {
}
/**
+ * testDeleteAllFailedFind method
+ *
+ * Eg: Behavior callback stops the event, find returns null
+ *
+ * @return void
+ */
+ public function testDeleteAllFailedFind() {
+ $this->loadFixtures('Article');
+ $this->getMock('Article', array('find'), array(), 'ArticleDeleteAll');
+
+ $TestModel = new ArticleDeleteAll();
+ $TestModel->expects($this->once())
+ ->method('find')
+ ->will($this->returnValue(null));
+
+ $result = $TestModel->deleteAll(array('Article.user_id' => 999));
+ $this->assertFalse($result);
+ }
+
+/**
* testRecursiveDel method
*
* @return void
View
24 lib/Cake/Test/Case/Model/ModelReadTest.php
@@ -3006,6 +3006,30 @@ public function testSelfAssociationAfterFind() {
}
/**
+ * Test that afterFind can completely unset data.
+ *
+ * @return void
+ */
+ public function testAfterFindUnset() {
+ $this->loadFixtures('Article', 'Comment', 'User');
+ $model = new CustomArticle();
+ $model->bindModel(array(
+ 'hasMany' => array(
+ 'ModifiedComment' => array(
+ 'className' => 'ModifiedComment',
+ 'foreignKey' => 'article_id',
+ )
+ )
+ ));
+ $model->ModifiedComment->remove = true;
+ $result = $model->find('all');
+ $this->assertTrue(
+ empty($result[0]['ModifiedComment']),
+ 'Zeroith row should be removed by afterFind'
+ );
+ }
+
+/**
* testFindThreadedNoParent method
*
* @return void
View
10 lib/Cake/Test/Case/Model/models.php
@@ -552,6 +552,13 @@ class ModifiedComment extends CakeTestModel {
public $useTable = 'comments';
/**
+ * Property used to toggle filtering of results
+ *
+ * @var boolean
+ */
+ public $remove = false;
+
+/**
* belongsTo property
*
* @var array
@@ -567,6 +574,9 @@ public function afterFind($results, $primary = false) {
if (isset($results[0])) {
$results[0]['Comment']['callback'] = 'Fire';
}
+ if ($this->remove) {
+ return array();
+ }
return $results;
}
View
8 lib/Cake/Test/Case/Network/CakeRequestTest.php
@@ -136,6 +136,14 @@ public function testQueryStringAndNamedParams() {
$_SERVER['REQUEST_URI'] = '/tasks/index/page:1/?ts=123456';
$request = new CakeRequest();
$this->assertEquals('tasks/index/page:1/', $request->url);
+
+ $_SERVER['REQUEST_URI'] = '/some/path?url=http://cakephp.org';
+ $request = new CakeRequest();
+ $this->assertEquals('some/path', $request->url);
+
+ $_SERVER['REQUEST_URI'] = FULL_BASE_URL . '/other/path?url=http://cakephp.org';
+ $request = new CakeRequest();
+ $this->assertEquals('other/path', $request->url);
}
/**
View
6 lib/Cake/Test/Case/Utility/CakeTimeTest.php
@@ -367,6 +367,12 @@ public function testNiceShort() {
$time = time() + DAY;
$this->assertEquals('Tomorrow, ' . date('H:i', $time), $this->Time->niceShort($time));
+ $time = strtotime('+6 days');
+ $this->assertEquals('On ' . date('l F d, H:i', $time), $this->Time->niceShort($time));
+
+ $time = strtotime('-6 days');
+ $this->assertEquals(date('l F d, H:i', $time), $this->Time->niceShort($time));
+
date_default_timezone_set('Europe/London');
$result = $this->Time->niceShort('2005-01-15 10:00:00', new DateTimeZone('Europe/Brussels'));
$this->assertEquals('Jan 15th 2005, 11:00', $result);
View
11 lib/Cake/Test/Case/Utility/HashTest.php
@@ -170,6 +170,17 @@ public static function userData() {
* return void
*/
public function testGet() {
+ $data = array('abc', 'def');
+
+ $result = Hash::get($data, '0');
+ $this->assertEquals('abc', $result);
+
+ $result = Hash::get($data, 0);
+ $this->assertEquals('abc', $result);
+
+ $result = Hash::get($data, '1');
+ $this->assertEquals('def', $result);
+
$data = self::articleData();
$result = Hash::get(array(), '1.Article.title');
View
28 lib/Cake/Test/Case/View/Helper/FormHelperTest.php
@@ -607,6 +607,23 @@ public function testCreateWithSecurity() {
}
/**
+ * testFormCreateGetNoSecurity method
+ *
+ * Test form->create() with no security key as its a get form
+ *
+ * @return void
+ */
+ public function testCreateEndGetNoSecurity() {
+ $this->Form->request['_Token'] = array('key' => 'testKey');
+ $encoding = strtolower(Configure::read('App.encoding'));
+ $result = $this->Form->create('Contact', array('type' => 'get', 'url' => '/contacts/add'));
+ $this->assertNotContains('Token', $result);
+
+ $result = $this->Form->end('Save');
+ $this->assertNotContains('Token', $result);
+ }
+
+/**
* test that create() clears the fields property so it starts fresh
*
* @return void
@@ -3951,6 +3968,17 @@ public function testSelect() {
'/select'
);
$this->assertTags($result, $expected);
+
+ $this->Form->request->data['Model']['field'] = 50;
+ $result = $this->Form->select('Model.field', array('50f5c0cf' => 'Stringy', '50' => 'fifty'));
+ $expected = array(
+ 'select' => array('name' => 'data[Model][field]', 'id' => 'ModelField'),
+ array('option' => array('value' => '')), '/option',
+ array('option' => array('value' => '50f5c0cf')), 'Stringy', '/option',
+ array('option' => array('value' => '50', 'selected' => 'selected')), 'fifty', '/option',
+ '/select'
+ );
+ $this->assertTags($result, $expected);
}
/**
View
2  lib/Cake/Utility/CakeTime.php
@@ -56,7 +56,7 @@ class CakeTime {
* @var string
* @see CakeTime::niceShort()
*/
- public static $niceShortFormat = '%d/%m, %H:%M';
+ public static $niceShortFormat = '%B %d, %H:%M';
/**
* The format to use when formatting a time using `CakeTime::timeAgoInWords()`
View
4 lib/Cake/Utility/Hash.php
@@ -39,10 +39,10 @@ class Hash {
* @return mixed The value fetched from the array, or null.
*/
public static function get(array $data, $path) {
- if (empty($data) || empty($path)) {
+ if (empty($data)) {
return null;
}
- if (is_string($path)) {
+ if (is_string($path) || is_numeric($path)) {
$parts = explode('.', $path);
} else {
$parts = $path;
View
2  lib/Cake/Utility/Xml.php
@@ -101,7 +101,7 @@ public static function build($input, $options = array()) {
} elseif (file_exists($input)) {
return self::_loadXml(file_get_contents($input), $options);
} elseif (strpos($input, 'http://') === 0 || strpos($input, 'https://') === 0) {
- $socket = new HttpSocket();
+ $socket = new HttpSocket(array('request' => array('redirect' => 10)));
$response = $socket->get($input);
if (!$response->isOk()) {
throw new XmlException(__d('cake_dev', 'XML cannot be read.'));
View
12 lib/Cake/View/Helper/FormHelper.php
@@ -433,7 +433,9 @@ public function create($model = null, $options = array()) {
$htmlAttributes = array_merge($options, $htmlAttributes);
$this->fields = array();
- $append .= $this->_csrfField();
+ if ($this->requestType !== 'get') {
+ $append .= $this->_csrfField();
+ }
if (!empty($append)) {
$append = $this->Html->useTag('hiddenblock', $append);
@@ -504,7 +506,11 @@ public function end($options = null) {
}
$out .= $this->submit($submit, $submitOptions);
}
- if (isset($this->request['_Token']) && !empty($this->request['_Token'])) {
+ if (
+ $this->requestType !== 'get' &&
+ isset($this->request['_Token']) &&
+ !empty($this->request['_Token'])
+ ) {
$out .= $this->secure($this->fields);
$this->fields = array();
}
@@ -2602,7 +2608,7 @@ protected function _selectOptions($elements = array(), $parents = array(), $show
if ($name !== null) {
if (
(!$selectedIsArray && !$selectedIsEmpty && (string)$attributes['value'] == (string)$name) ||
- ($selectedIsArray && in_array($name, $attributes['value']))
+ ($selectedIsArray && in_array($name, $attributes['value'], true))
) {
if ($attributes['style'] === 'checkbox') {
$htmlOptions['checked'] = true;
View
6 lib/Cake/View/Helper/HtmlHelper.php
@@ -616,7 +616,7 @@ public function scriptEnd() {
* ### Usage:
*
* {{{
- * echo $html->style(array('margin' => '10px', 'padding' => '10px'), true);
+ * echo $this->Html->style(array('margin' => '10px', 'padding' => '10px'), true);
*
* // creates
* 'margin:10px;padding:10px;'
@@ -760,11 +760,11 @@ protected function _prepareCrumbs($startText) {
*
* Create a regular image:
*
- * `echo $html->image('cake_icon.png', array('alt' => 'CakePHP'));`
+ * `echo $this->Html->image('cake_icon.png', array('alt' => 'CakePHP'));`
*
* Create an image link:
*
- * `echo $html->image('cake_icon.png', array('alt' => 'CakePHP', 'url' => 'http://cakephp.org'));`
+ * `echo $this->Html->image('cake_icon.png', array('alt' => 'CakePHP', 'url' => 'http://cakephp.org'));`
*
* ### Options:
*
Please sign in to comment.
Something went wrong with that request. Please try again.