Merge branch '2.0' into 2.1

This commit is contained in:
mark_story 2011-10-25 22:29:03 -04:00
commit ad524b25ef
20 changed files with 148 additions and 89 deletions

View file

@ -1,2 +1,2 @@
<?php echo $xml->header(); ?>
<?php echo $content_for_layout; ?>
<?php echo '<?xml version="1.0" encoding="' . Configure::read('App.encoding') . '"?>'; ?>
<?php echo $content_for_layout; ?>

View file

@ -68,6 +68,9 @@ if (!defined('WWW_ROOT')) {
}
if (!defined('CAKE_CORE_INCLUDE_PATH')) {
if (function_exists('ini_set')) {
ini_set('include_path', ROOT . DS . 'lib' . PATH_SEPARATOR . ini_get('include_path'));
}
if (!include('Cake' . DS . 'bootstrap.php')) {
$failed = true;
}

View file

@ -306,18 +306,21 @@ class CakeSchema extends Object {
$systemTables = array(
'aros', 'acos', 'aros_acos', Configure::read('Session.table'), 'i18n'
);
$fulltable = $db->fullTableName($Object, false);
if (in_array($table, $systemTables)) {
$tables[$Object->table] = $this->_columns($Object);
$tables[$Object->table]['indexes'] = $db->index($Object);
$tables[$Object->table]['tableParameters'] = $db->readTableParameters($table);
$tables[$Object->table]['tableParameters'] = $db->readTableParameters($fulltable);
} elseif ($models === false) {
$tables[$table] = $this->_columns($Object);
$tables[$table]['indexes'] = $db->index($Object);
$tables[$table]['tableParameters'] = $db->readTableParameters($table);
$tables[$table]['tableParameters'] = $db->readTableParameters($fulltable);
} else {
$tables['missing'][$table] = $this->_columns($Object);
$tables['missing'][$table]['indexes'] = $db->index($Object);
$tables['missing'][$table]['tableParameters'] = $db->readTableParameters($table);
$tables['missing'][$table]['tableParameters'] = $db->readTableParameters($fulltable);
}
}
}

View file

@ -105,7 +105,7 @@ class CakeRequest implements ArrayAccess {
'flash' => array('env' => 'HTTP_USER_AGENT', 'pattern' => '/^(Shockwave|Adobe) Flash/'),
'mobile' => array('env' => 'HTTP_USER_AGENT', 'options' => array(
'Android', 'AvantGo', 'BlackBerry', 'DoCoMo', 'Fennec', 'iPod', 'iPhone',
'J2ME', 'MIDP', 'NetFront', 'Nokia', 'Opera Mini', 'PalmOS', 'PalmSource',
'J2ME', 'MIDP', 'NetFront', 'Nokia', 'Opera Mini', 'Opera Mobi', 'PalmOS', 'PalmSource',
'portalmmm', 'Plucker', 'ReqwirelessWeb', 'SonyEricsson', 'Symbian', 'UP\\.Browser',
'webOS', 'Windows CE', 'Xiino'
)),

View file

@ -313,9 +313,9 @@ class CakeResponse {
* Class constructor
*
* @param array $options list of parameters to setup the response. Possible values are:
* - body: the rensonse text that should be sent to the client
* - body: the response text that should be sent to the client
* - status: the HTTP status code to respond with
* - type: a complete mime-type string or an extension mapepd in this class
* - type: a complete mime-type string or an extension mapped in this class
* - charset: the charset for the response body
*/
public function __construct(array $options = array()) {

View file

@ -280,6 +280,7 @@ class CakeRoute {
$separatorIsPresent = strpos($param, $namedConfig['separator']) !== false;
if ((!isset($this->options['named']) || !empty($this->options['named'])) && $separatorIsPresent) {
list($key, $val) = explode($namedConfig['separator'], $param, 2);
$val = urldecode($val);
$hasRule = isset($rules[$key]);
$passIt = (!$hasRule && !$greedy) || ($hasRule && !$this->_matchNamed($val, $rules[$key], $context));
if ($passIt) {

View file

@ -121,11 +121,11 @@ class ProjectTaskTest extends CakeTestCase {
$this->Task->execute();
$this->assertTrue(is_dir($this->Task->args[0]), 'No project dir');
$file = new File($path . DS . 'webroot' . DS . 'index.php');
$contents = $file->read();
$File = new File($path . DS . 'webroot' . DS . 'index.php');
$contents = $File->read();
$this->assertRegExp('/define\(\'CAKE_CORE_INCLUDE_PATH\', .*?DS/', $contents);
$file = new File($path . DS . 'webroot' . DS . 'test.php');
$contents = $file->read();
$File = new File($path . DS . 'webroot' . DS . 'test.php');
$contents = $File->read();
$this->assertRegExp('/define\(\'CAKE_CORE_INCLUDE_PATH\', .*?DS/', $contents);
}
@ -197,8 +197,8 @@ class ProjectTaskTest extends CakeTestCase {
$result = $this->Task->securitySalt($path);
$this->assertTrue($result);
$file = new File($path . 'Config' . DS . 'core.php');
$contents = $file->read();
$File = new File($path . 'Config' . DS . 'core.php');
$contents = $File->read();
$this->assertNoPattern('/DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi/', $contents, 'Default Salt left behind. %s');
}
@ -214,8 +214,8 @@ class ProjectTaskTest extends CakeTestCase {
$result = $this->Task->securityCipherSeed($path);
$this->assertTrue($result);
$file = new File($path . 'Config' . DS . 'core.php');
$contents = $file->read();
$File = new File($path . 'Config' . DS . 'core.php');
$contents = $File->read();
$this->assertNoPattern('/76859309657453542496749683645/', $contents, 'Default CipherSeed left behind. %s');
}
@ -230,11 +230,11 @@ class ProjectTaskTest extends CakeTestCase {
$path = $this->Task->path . 'bake_test_app' . DS;
$this->Task->corePath($path);
$file = new File($path . 'webroot' . DS . 'index.php');
$contents = $file->read();
$File = new File($path . 'webroot' . DS . 'index.php');
$contents = $File->read();
$this->assertNoPattern('/define\(\'CAKE_CORE_INCLUDE_PATH\', ROOT/', $contents);
$file = new File($path . 'webroot' . DS . 'test.php');
$contents = $file->read();
$File = new File($path . 'webroot' . DS . 'test.php');
$contents = $File->read();
$this->assertNoPattern('/define\(\'CAKE_CORE_INCLUDE_PATH\', ROOT/', $contents);
}
@ -256,8 +256,8 @@ class ProjectTaskTest extends CakeTestCase {
$result = $this->Task->getPrefix();
$this->assertEqual($result, 'super_duper_admin_');
$file = new File($this->Task->configPath . 'core.php');
$file->delete();
$File = new File($this->Task->configPath . 'core.php');
$File->delete();
}
/**
@ -266,10 +266,10 @@ class ProjectTaskTest extends CakeTestCase {
* @return void
*/
public function testCakeAdmin() {
$file = new File(APP . 'Config' . DS . 'core.php');
$contents = $file->read();
$file = new File(TMP . 'tests' . DS . 'core.php');
$file->write($contents);
$File = new File(APP . 'Config' . DS . 'core.php');
$contents = $File->read();
$File = new File(TMP . 'tests' . DS . 'core.php');
$File->write($contents);
Configure::write('Routing.prefixes', null);
$this->Task->configPath = TMP . 'tests' . DS;
@ -277,7 +277,7 @@ class ProjectTaskTest extends CakeTestCase {
$this->assertTrue($result);
$this->assertEqual(Configure::read('Routing.prefixes'), array('my_prefix'));
$file->delete();
$File->delete();
}
/**
@ -332,8 +332,8 @@ class ProjectTaskTest extends CakeTestCase {
$result = $this->Task->consolePath($path);
$this->assertTrue($result);
$file = new File($path . 'Console' . DS . 'cake.php');
$contents = $file->read();
$File = new File($path . 'Console' . DS . 'cake.php');
$contents = $File->read();
$this->assertNoPattern('/__CAKE_PATH__/', $contents, 'Console path placeholder left behind.');
}
}

View file

@ -381,6 +381,22 @@ class CakeRouteTest extends CakeTestCase {
$this->assertFalse($result);
}
/**
* Ensure that named parameters are urldecoded
*
* @return void
*/
public function testParseNamedParametersUrlDecode() {
Router::connectNamed(true);
$route = new CakeRoute('/:controller/:action/*', array('plugin' => null));
$result = $route->parse('/posts/index/page:%CE%98');
$this->assertEquals('Θ', $result['named']['page']);
$result = $route->parse('/posts/index/page[]:%CE%98');
$this->assertEquals('Θ', $result['named']['page'][0]);
}
/**
* test that named params with null/false are excluded
*

View file

@ -428,9 +428,9 @@ class FileTest extends CakeTestCase {
if (!file_exists($tmpFile)) {
touch($tmpFile);
}
$file =& new File($tmpFile);
$file->read();
$this->assertTrue($file->delete());
$File =& new File($tmpFile);
$File->read();
$this->assertTrue($File->delete());
}
/**

View file

@ -122,16 +122,16 @@ class FolderTest extends CakeTestCase {
* @return void
*/
public function testCreation() {
$folder = new Folder(TMP . 'tests');
$result = $folder->create(TMP . 'tests' . DS . 'first' . DS . 'second' . DS . 'third');
$Folder = new Folder(TMP . 'tests');
$result = $Folder->create(TMP . 'tests' . DS . 'first' . DS . 'second' . DS . 'third');
$this->assertTrue($result);
rmdir(TMP . 'tests' . DS . 'first' . DS . 'second' . DS . 'third');
rmdir(TMP . 'tests' . DS . 'first' . DS . 'second');
rmdir(TMP . 'tests' . DS . 'first');
$folder = new Folder(TMP . 'tests');
$result = $folder->create(TMP . 'tests' . DS . 'first');
$Folder = new Folder(TMP . 'tests');
$result = $Folder->create(TMP . 'tests' . DS . 'first');
$this->assertTrue($result);
rmdir(TMP . 'tests' . DS . 'first');
}
@ -142,15 +142,15 @@ class FolderTest extends CakeTestCase {
* @return void
*/
public function testCreateWithTrailingDs() {
$folder = new Folder(TMP);
$Folder = new Folder(TMP);
$path = TMP . 'tests' . DS . 'trailing' . DS . 'dir' . DS;
$result = $folder->create($path);
$result = $Folder->create($path);
$this->assertTrue($result);
$this->assertTrue(is_dir($path), 'Folder was not made');
$folder = new Folder(TMP . 'tests' . DS . 'trailing');
$this->assertTrue($folder->delete());
$Folder = new Folder(TMP . 'tests' . DS . 'trailing');
$this->assertTrue($Folder->delete());
}
/**
@ -166,8 +166,8 @@ class FolderTest extends CakeTestCase {
chmod($path, '0444');
try {
$folder = new Folder($path);
$result = $folder->create($path . DS . 'two' . DS . 'three');
$Folder = new Folder($path);
$result = $Folder->create($path . DS . 'two' . DS . 'three');
$this->assertFalse($result);
} catch (PHPUnit_Framework_Error $e) {
$this->assertTrue(true);
@ -537,7 +537,7 @@ class FolderTest extends CakeTestCase {
$this->assertSame($expected, $result);
$Folder->cd(TMP);
$file = new File($Folder->pwd() . DS . 'paths.php', true);
$File = new File($Folder->pwd() . DS . 'paths.php', true);
$Folder->create($Folder->pwd() . DS . 'testme');
$Folder->cd('testme');
$result = $Folder->find('paths\.php');
@ -551,7 +551,7 @@ class FolderTest extends CakeTestCase {
$Folder->cd(TMP);
$Folder->delete($Folder->pwd() . DS . 'testme');
$file->delete();
$File->delete();
}
/**

View file

@ -67,6 +67,7 @@ class InflectorTest extends CakeTestCase {
$this->assertEqual(Inflector::singularize('Aliases'), 'Alias');
$this->assertEqual(Inflector::singularize('Alias'), 'Alias');
$this->assertEqual(Inflector::singularize('Media'), 'Media');
$this->assertEqual(Inflector::singularize('NodeMedia'), 'NodeMedia');
$this->assertEqual(Inflector::singularize('alumni'), 'alumnus');
$this->assertEqual(Inflector::singularize('bacilli'), 'bacillus');
$this->assertEqual(Inflector::singularize('cacti'), 'cactus');
@ -135,6 +136,7 @@ class InflectorTest extends CakeTestCase {
$this->assertEqual(Inflector::pluralize('Alias'), 'Aliases');
$this->assertEqual(Inflector::pluralize('Aliases'), 'Aliases');
$this->assertEqual(Inflector::pluralize('Media'), 'Media');
$this->assertEqual(Inflector::pluralize('NodeMedia'), 'NodeMedia');
$this->assertEqual(Inflector::pluralize('alumnus'), 'alumni');
$this->assertEqual(Inflector::pluralize('bacillus'), 'bacilli');
$this->assertEqual(Inflector::pluralize('cactus'), 'cacti');

View file

@ -3441,6 +3441,27 @@ class FormHelperTest extends CakeTestCase {
);
$this->assertTags($result, $expected);
$options = array(
array('value' => 'first', 'name' => 'First'),
array('value' => 'first', 'name' => 'Another First'),
);
$result = $this->Form->select(
'Model.field',
$options,
array('escape' => false, 'empty' => false)
);
$expected = array(
'select' => array('name' => 'data[Model][field]', 'id' => 'ModelField'),
array('option' => array('value' => 'first')),
'First',
'/option',
array('option' => array('value' => 'first')),
'Another First',
'/option',
'/select'
);
$this->assertTags($result, $expected);
$this->Form->request->data = array('Model' => array('contact_id' => 228));
$result = $this->Form->select(
'Model.contact_id',

View file

@ -378,7 +378,7 @@ class HtmlHelperTest extends CakeTestCase {
App::uses('File', 'Utility');
$testfile = WWW_ROOT . 'theme' . DS . 'test_theme' . DS . 'img' . DS . '__cake_test_image.gif';
$file = new File($testfile, true);
$File = new File($testfile, true);
App::build(array(
'views' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View'. DS)
@ -662,7 +662,7 @@ class HtmlHelperTest extends CakeTestCase {
App::uses('File', 'Utility');
$testfile = WWW_ROOT . 'theme' . DS . 'test_theme' . DS . 'js' . DS . '__test_js.js';
$file = new File($testfile, true);
$File = new File($testfile, true);
App::build(array(
'views' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View'. DS)
@ -676,8 +676,8 @@ class HtmlHelperTest extends CakeTestCase {
);
$this->assertTags($result, $expected);
$folder = new Folder(WWW_ROOT . 'theme' . DS . 'test_theme');
$folder->delete();
$Folder = new Folder(WWW_ROOT . 'theme' . DS . 'test_theme');
$Folder->delete();
App::build();
}

View file

@ -348,6 +348,25 @@ class HelperTest extends CakeTestCase {
$this->assertEquals(array('Tag', 'Tag'), $this->Helper->entity());
}
/**
* Test that habtm associations can have property fields created.
*
* @return void
*/
public function testSetEntityHabtmPropertyFieldNames() {
$this->Helper->fieldset = array(
'HelperTestComment' => array(
'fields' => array('Tag' => array('type' => 'multiple'))
)
);
$this->Helper->setEntity('HelperTestComment', true);
$this->Helper->setEntity('Tag.name');
$this->assertEquals('Tag', $this->Helper->model());
$this->assertEquals('name', $this->Helper->field());
$this->assertEquals(array('Tag', 'name'), $this->Helper->entity());
}
/**
* test that 'view' doesn't break things.
*

View file

@ -29,8 +29,8 @@ class CakeTestSuite extends PHPUnit_Framework_TestSuite {
* @return void
*/
public function addTestDirectory($directory = '.') {
$folder = new Folder($directory);
list($dirs, $files) = $folder->read(true, true, true);
$Folder = new Folder($directory);
list($dirs, $files) = $Folder->read(true, true, true);
foreach ($files as $file) {
$this->addTestFile($file);
@ -44,8 +44,8 @@ class CakeTestSuite extends PHPUnit_Framework_TestSuite {
* @return void
*/
public function addTestDirectoryRecursive($directory = '.') {
$folder = new Folder($directory);
$files = $folder->tree(null, false, 'files');
$Folder = new Folder($directory);
$files = $Folder->tree(null, false, 'files');
foreach ($files as $file) {
$this->addTestFile($file);

View file

@ -160,12 +160,12 @@ class Inflector {
'debris', 'diabetes', 'djinn', 'eland', 'elk', 'equipment', 'Faroese', 'flounder',
'Foochowese', 'gallows', 'Genevese', 'Genoese', 'Gilbertese', 'graffiti',
'headquarters', 'herpes', 'hijinks', 'Hottentotese', 'information', 'innings',
'jackanapes', 'Kiplingese', 'Kongoese', 'Lucchese', 'mackerel', 'Maltese', 'media',
'jackanapes', 'Kiplingese', 'Kongoese', 'Lucchese', 'mackerel', 'Maltese', '.*?media',
'mews', 'moose', 'mumps', 'Nankingese', 'news', 'nexus', 'Niasese',
'Pekingese', 'Piedmontese', 'pincers', 'Pistoiese', 'pliers', 'Portuguese',
'proceedings', 'rabies', 'rice', 'rhinoceros', 'salmon', 'Sarawakese', 'scissors',
'sea[- ]bass', 'series', 'Shavese', 'shears', 'siemens', 'species', 'swine', 'testes',
'trousers', 'trout','tuna', 'Vermontese', 'Wenchowese', 'whiting', 'wildebeest',
'trousers', 'trout', 'tuna', 'Vermontese', 'Wenchowese', 'whiting', 'wildebeest',
'Yengeese'
);

View file

@ -453,21 +453,21 @@ class Helper extends Object {
$this->_association = null;
// habtm models are special
if (
$isHabtm = (
isset($this->fieldset[$this->_modelScope]['fields'][$parts[0]]['type']) &&
$this->fieldset[$this->_modelScope]['fields'][$parts[0]]['type'] === 'multiple'
) {
$this->fieldset[$this->_modelScope]['fields'][$parts[0]]['type'] === 'multiple' &&
$count == 1
);
// habtm models are special
if ($count == 1 && $isHabtm) {
$this->_association = $parts[0];
$entity = $parts[0] . '.' . $parts[0];
} else {
// check for associated model.
$reversed = array_reverse($parts);
foreach ($reversed as $part) {
if (
!isset($this->fieldset[$this->_modelScope]['fields'][$part]) &&
preg_match('/^[A-Z]/', $part)
) {
foreach ($reversed as $i => $part) {
if ($i > 0 && preg_match('/^[A-Z]/', $part)) {
$this->_association = $part;
break;
}

View file

@ -196,11 +196,11 @@ class FormHelper extends AppHelper {
if ($key === 'fields') {
if (!isset($this->fieldset[$model]['fields'])) {
$fields = $this->fieldset[$model]['fields'] = $object->schema();
}
if (empty($field)) {
foreach ($object->hasAndBelongsToMany as $alias => $assocData) {
$this->fieldset[$object->alias]['fields'][$alias] = array('type' => 'multiple');
}
}
if (empty($field)) {
return $this->fieldset[$model]['fields'];
} elseif (isset($this->fieldset[$model]['fields'][$field])) {
return $this->fieldset[$model]['fields'][$field];
@ -305,11 +305,12 @@ class FormHelper extends AppHelper {
* will be appended.
* - `onsubmit` Used in conjunction with 'default' to create ajax forms.
* - `inputDefaults` set the default $options for FormHelper::input(). Any options that would
* be set when using FormHelper::input() can be set here. Options set with `inputDefaults`
* can be overridden when calling input()
* be set when using FormHelper::input() can be set here. Options set with `inputDefaults`
* can be overridden when calling input()
* - `encoding` Set the accept-charset encoding for the form. Defaults to `Configure::read('App.encoding')`
*
* @param string $model The model object which the form is being defined for
* @param string $model The model object which the form is being defined for. Should
* include the plugin name for plugin forms. e.g. `ContactManager.Contact`.
* @param array $options An array of html attributes and options.
* @return string An formatted opening FORM tag.
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#options-for-create
@ -444,6 +445,7 @@ class FormHelper extends AppHelper {
if ($model !== false) {
$this->setEntity($model, true);
$this->_introspectModel($model, 'fields');
}
return $this->Html->useTag('form', $action, $htmlAttributes) . $append;
}
@ -1245,7 +1247,7 @@ class FormHelper extends AppHelper {
* - `value` - indicate a value that is should be checked
* - `label` - boolean to indicate whether or not labels for widgets show be displayed
* - `hiddenField` - boolean to indicate if you want the results of radio() to include
* a hidden input with a value of ''. This is useful for creating radio sets that non-continuous
* a hidden input with a value of ''. This is useful for creating radio sets that non-continuous
*
* @param string $fieldName Name of a field, like this "Modelname.fieldname"
* @param array $options Radio button options array.
@ -1694,6 +1696,16 @@ class FormHelper extends AppHelper {
* In the above `2 => 'fred'` will not generate an option element. You should enable the `showParents`
* attribute to show the fred option.
*
* If you have multiple options that need to have the same value attribute, you can
* use an array of arrays to express this:
*
* {{{
* $options = array(
* array('name' => 'United states', 'value' => 'USA'),
* array('name' => 'USA', 'value' => 'USA'),
* );
* }}}
*
* @param string $fieldName Name attribute of the SELECT
* @param array $options Array of the OPTION elements (as 'value'=>'Text' pairs) to be used in the
* SELECT element
@ -2223,24 +2235,6 @@ class FormHelper extends AppHelper {
return $opt;
}
/**
* Add support for special HABTM syntax.
*
* Sets this helper's model and field properties to the dot-separated value-pair in $entity.
*
* @param mixed $entity A field name, like "ModelName.fieldName" or "ModelName.ID.fieldName"
* @param boolean $setScope Sets the view scope to the model specified in $tagValue
* @return void
*/
public function setEntity($entity, $setScope = false) {
parent::setEntity($entity, $setScope);
$parts = explode('.', $entity);
$field = $this->_introspectModel($this->_modelScope, 'fields', $parts[0]);
if (!empty($field) && $field['type'] === 'multiple') {
$this->_entityPath = $parts[0] . '.' . $parts[0];
}
}
/**
* Gets the input field name for the current tag
*

View file

@ -138,7 +138,7 @@ You can also add some CSS styles for your pages at: APP/webroot/css.');
<p>
<?php
echo $this->Html->link(
sprintf('<strong>%s</strong> %s', __d('cake_dev', 'New'), __d('cake_dev', 'CakePHP 1.3 Docs')),
sprintf('<strong>%s</strong> %s', __d('cake_dev', 'New'), __d('cake_dev', 'CakePHP 2.0 Docs')),
'http://book.cakephp.org/2.0/en/',
array('target' => '_blank', 'escape' => false)
);

View file

@ -26,7 +26,7 @@ App::uses('View', 'View');
* the default app view files will be used. You can set `$this->theme` and `$this->viewClass = 'Theme'`
* in your Controller to use the ThemeView.
*
* Example of theme path with `$this->theme = 'super_hot';` Would be `app/View/Themed/SuperHot/Posts`
* Example of theme path with `$this->theme = 'SuperHot';` Would be `app/View/Themed/SuperHot/Posts`
*
* @package Cake.View
*/