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 '<?xml version="1.0" encoding="' . Configure::read('App.encoding') . '"?>'; ?>
<?php echo $content_for_layout; ?> <?php echo $content_for_layout; ?>

View file

@ -68,6 +68,9 @@ if (!defined('WWW_ROOT')) {
} }
if (!defined('CAKE_CORE_INCLUDE_PATH')) { 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')) { if (!include('Cake' . DS . 'bootstrap.php')) {
$failed = true; $failed = true;
} }

View file

@ -306,18 +306,21 @@ class CakeSchema extends Object {
$systemTables = array( $systemTables = array(
'aros', 'acos', 'aros_acos', Configure::read('Session.table'), 'i18n' 'aros', 'acos', 'aros_acos', Configure::read('Session.table'), 'i18n'
); );
$fulltable = $db->fullTableName($Object, false);
if (in_array($table, $systemTables)) { if (in_array($table, $systemTables)) {
$tables[$Object->table] = $this->_columns($Object); $tables[$Object->table] = $this->_columns($Object);
$tables[$Object->table]['indexes'] = $db->index($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) { } elseif ($models === false) {
$tables[$table] = $this->_columns($Object); $tables[$table] = $this->_columns($Object);
$tables[$table]['indexes'] = $db->index($Object); $tables[$table]['indexes'] = $db->index($Object);
$tables[$table]['tableParameters'] = $db->readTableParameters($table); $tables[$table]['tableParameters'] = $db->readTableParameters($fulltable);
} else { } else {
$tables['missing'][$table] = $this->_columns($Object); $tables['missing'][$table] = $this->_columns($Object);
$tables['missing'][$table]['indexes'] = $db->index($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/'), 'flash' => array('env' => 'HTTP_USER_AGENT', 'pattern' => '/^(Shockwave|Adobe) Flash/'),
'mobile' => array('env' => 'HTTP_USER_AGENT', 'options' => array( 'mobile' => array('env' => 'HTTP_USER_AGENT', 'options' => array(
'Android', 'AvantGo', 'BlackBerry', 'DoCoMo', 'Fennec', 'iPod', 'iPhone', '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', 'portalmmm', 'Plucker', 'ReqwirelessWeb', 'SonyEricsson', 'Symbian', 'UP\\.Browser',
'webOS', 'Windows CE', 'Xiino' 'webOS', 'Windows CE', 'Xiino'
)), )),

View file

@ -313,9 +313,9 @@ class CakeResponse {
* Class constructor * Class constructor
* *
* @param array $options list of parameters to setup the response. Possible values are: * @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 * - 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 * - charset: the charset for the response body
*/ */
public function __construct(array $options = array()) { public function __construct(array $options = array()) {

View file

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

View file

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

View file

@ -381,6 +381,22 @@ class CakeRouteTest extends CakeTestCase {
$this->assertFalse($result); $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 * test that named params with null/false are excluded
* *

View file

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

View file

@ -122,16 +122,16 @@ class FolderTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testCreation() { public function testCreation() {
$folder = new Folder(TMP . 'tests'); $Folder = new Folder(TMP . 'tests');
$result = $folder->create(TMP . 'tests' . DS . 'first' . DS . 'second' . DS . 'third'); $result = $Folder->create(TMP . 'tests' . DS . 'first' . DS . 'second' . DS . 'third');
$this->assertTrue($result); $this->assertTrue($result);
rmdir(TMP . 'tests' . DS . 'first' . DS . 'second' . DS . 'third'); rmdir(TMP . 'tests' . DS . 'first' . DS . 'second' . DS . 'third');
rmdir(TMP . 'tests' . DS . 'first' . DS . 'second'); rmdir(TMP . 'tests' . DS . 'first' . DS . 'second');
rmdir(TMP . 'tests' . DS . 'first'); rmdir(TMP . 'tests' . DS . 'first');
$folder = new Folder(TMP . 'tests'); $Folder = new Folder(TMP . 'tests');
$result = $folder->create(TMP . 'tests' . DS . 'first'); $result = $Folder->create(TMP . 'tests' . DS . 'first');
$this->assertTrue($result); $this->assertTrue($result);
rmdir(TMP . 'tests' . DS . 'first'); rmdir(TMP . 'tests' . DS . 'first');
} }
@ -142,15 +142,15 @@ class FolderTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testCreateWithTrailingDs() { public function testCreateWithTrailingDs() {
$folder = new Folder(TMP); $Folder = new Folder(TMP);
$path = TMP . 'tests' . DS . 'trailing' . DS . 'dir' . DS; $path = TMP . 'tests' . DS . 'trailing' . DS . 'dir' . DS;
$result = $folder->create($path); $result = $Folder->create($path);
$this->assertTrue($result); $this->assertTrue($result);
$this->assertTrue(is_dir($path), 'Folder was not made'); $this->assertTrue(is_dir($path), 'Folder was not made');
$folder = new Folder(TMP . 'tests' . DS . 'trailing'); $Folder = new Folder(TMP . 'tests' . DS . 'trailing');
$this->assertTrue($folder->delete()); $this->assertTrue($Folder->delete());
} }
/** /**
@ -166,8 +166,8 @@ class FolderTest extends CakeTestCase {
chmod($path, '0444'); chmod($path, '0444');
try { try {
$folder = new Folder($path); $Folder = new Folder($path);
$result = $folder->create($path . DS . 'two' . DS . 'three'); $result = $Folder->create($path . DS . 'two' . DS . 'three');
$this->assertFalse($result); $this->assertFalse($result);
} catch (PHPUnit_Framework_Error $e) { } catch (PHPUnit_Framework_Error $e) {
$this->assertTrue(true); $this->assertTrue(true);
@ -537,7 +537,7 @@ class FolderTest extends CakeTestCase {
$this->assertSame($expected, $result); $this->assertSame($expected, $result);
$Folder->cd(TMP); $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->create($Folder->pwd() . DS . 'testme');
$Folder->cd('testme'); $Folder->cd('testme');
$result = $Folder->find('paths\.php'); $result = $Folder->find('paths\.php');
@ -551,7 +551,7 @@ class FolderTest extends CakeTestCase {
$Folder->cd(TMP); $Folder->cd(TMP);
$Folder->delete($Folder->pwd() . DS . 'testme'); $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('Aliases'), 'Alias');
$this->assertEqual(Inflector::singularize('Alias'), 'Alias'); $this->assertEqual(Inflector::singularize('Alias'), 'Alias');
$this->assertEqual(Inflector::singularize('Media'), 'Media'); $this->assertEqual(Inflector::singularize('Media'), 'Media');
$this->assertEqual(Inflector::singularize('NodeMedia'), 'NodeMedia');
$this->assertEqual(Inflector::singularize('alumni'), 'alumnus'); $this->assertEqual(Inflector::singularize('alumni'), 'alumnus');
$this->assertEqual(Inflector::singularize('bacilli'), 'bacillus'); $this->assertEqual(Inflector::singularize('bacilli'), 'bacillus');
$this->assertEqual(Inflector::singularize('cacti'), 'cactus'); $this->assertEqual(Inflector::singularize('cacti'), 'cactus');
@ -135,6 +136,7 @@ class InflectorTest extends CakeTestCase {
$this->assertEqual(Inflector::pluralize('Alias'), 'Aliases'); $this->assertEqual(Inflector::pluralize('Alias'), 'Aliases');
$this->assertEqual(Inflector::pluralize('Aliases'), 'Aliases'); $this->assertEqual(Inflector::pluralize('Aliases'), 'Aliases');
$this->assertEqual(Inflector::pluralize('Media'), 'Media'); $this->assertEqual(Inflector::pluralize('Media'), 'Media');
$this->assertEqual(Inflector::pluralize('NodeMedia'), 'NodeMedia');
$this->assertEqual(Inflector::pluralize('alumnus'), 'alumni'); $this->assertEqual(Inflector::pluralize('alumnus'), 'alumni');
$this->assertEqual(Inflector::pluralize('bacillus'), 'bacilli'); $this->assertEqual(Inflector::pluralize('bacillus'), 'bacilli');
$this->assertEqual(Inflector::pluralize('cactus'), 'cacti'); $this->assertEqual(Inflector::pluralize('cactus'), 'cacti');

View file

@ -3441,6 +3441,27 @@ class FormHelperTest extends CakeTestCase {
); );
$this->assertTags($result, $expected); $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)); $this->Form->request->data = array('Model' => array('contact_id' => 228));
$result = $this->Form->select( $result = $this->Form->select(
'Model.contact_id', 'Model.contact_id',

View file

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

View file

@ -348,6 +348,25 @@ class HelperTest extends CakeTestCase {
$this->assertEquals(array('Tag', 'Tag'), $this->Helper->entity()); $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. * test that 'view' doesn't break things.
* *

View file

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

View file

@ -160,12 +160,12 @@ class Inflector {
'debris', 'diabetes', 'djinn', 'eland', 'elk', 'equipment', 'Faroese', 'flounder', 'debris', 'diabetes', 'djinn', 'eland', 'elk', 'equipment', 'Faroese', 'flounder',
'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',
'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', 'rice', 'rhinoceros', 'salmon', 'Sarawakese', 'scissors', 'proceedings', 'rabies', 'rice', 'rhinoceros', 'salmon', 'Sarawakese', 'scissors',
'sea[- ]bass', 'series', 'Shavese', 'shears', 'siemens', 'species', 'swine', 'testes', 'sea[- ]bass', 'series', 'Shavese', 'shears', 'siemens', 'species', 'swine', 'testes',
'trousers', 'trout','tuna', 'Vermontese', 'Wenchowese', 'whiting', 'wildebeest', 'trousers', 'trout', 'tuna', 'Vermontese', 'Wenchowese', 'whiting', 'wildebeest',
'Yengeese' 'Yengeese'
); );

View file

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

View file

@ -196,11 +196,11 @@ class FormHelper extends AppHelper {
if ($key === 'fields') { if ($key === 'fields') {
if (!isset($this->fieldset[$model]['fields'])) { if (!isset($this->fieldset[$model]['fields'])) {
$fields = $this->fieldset[$model]['fields'] = $object->schema(); $fields = $this->fieldset[$model]['fields'] = $object->schema();
}
if (empty($field)) {
foreach ($object->hasAndBelongsToMany as $alias => $assocData) { foreach ($object->hasAndBelongsToMany as $alias => $assocData) {
$this->fieldset[$object->alias]['fields'][$alias] = array('type' => 'multiple'); $this->fieldset[$object->alias]['fields'][$alias] = array('type' => 'multiple');
} }
}
if (empty($field)) {
return $this->fieldset[$model]['fields']; return $this->fieldset[$model]['fields'];
} elseif (isset($this->fieldset[$model]['fields'][$field])) { } elseif (isset($this->fieldset[$model]['fields'][$field])) {
return $this->fieldset[$model]['fields'][$field]; return $this->fieldset[$model]['fields'][$field];
@ -305,11 +305,12 @@ class FormHelper extends AppHelper {
* will be appended. * will be appended.
* - `onsubmit` Used in conjunction with 'default' to create ajax forms. * - `onsubmit` Used in conjunction with 'default' to create ajax forms.
* - `inputDefaults` set the default $options for FormHelper::input(). Any options that would * - `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` * be set when using FormHelper::input() can be set here. Options set with `inputDefaults`
* can be overridden when calling input() * can be overridden when calling input()
* - `encoding` Set the accept-charset encoding for the form. Defaults to `Configure::read('App.encoding')` * - `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. * @param array $options An array of html attributes and options.
* @return string An formatted opening FORM tag. * @return string An formatted opening FORM tag.
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#options-for-create * @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) { if ($model !== false) {
$this->setEntity($model, true); $this->setEntity($model, true);
$this->_introspectModel($model, 'fields');
} }
return $this->Html->useTag('form', $action, $htmlAttributes) . $append; 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 * - `value` - indicate a value that is should be checked
* - `label` - boolean to indicate whether or not labels for widgets show be displayed * - `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 * - `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 string $fieldName Name of a field, like this "Modelname.fieldname"
* @param array $options Radio button options array. * @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` * In the above `2 => 'fred'` will not generate an option element. You should enable the `showParents`
* attribute to show the fred option. * 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 string $fieldName Name attribute of the SELECT
* @param array $options Array of the OPTION elements (as 'value'=>'Text' pairs) to be used in the * @param array $options Array of the OPTION elements (as 'value'=>'Text' pairs) to be used in the
* SELECT element * SELECT element
@ -2223,24 +2235,6 @@ class FormHelper extends AppHelper {
return $opt; 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 * 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> <p>
<?php <?php
echo $this->Html->link( 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/', 'http://book.cakephp.org/2.0/en/',
array('target' => '_blank', 'escape' => false) 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'` * the default app view files will be used. You can set `$this->theme` and `$this->viewClass = 'Theme'`
* in your Controller to use the ThemeView. * 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 * @package Cake.View
*/ */