Merge remote-tracking branch 'origin/master' into 2.3

Conflicts:
	lib/Cake/Model/Behavior/TranslateBehavior.php
	lib/Cake/Model/CakeSchema.php
	lib/Cake/Utility/CakeTime.php
	lib/Cake/Utility/ClassRegistry.php
	lib/Cake/View/MediaView.php
This commit is contained in:
Jose Lorenzo Rodriguez 2012-09-25 16:36:03 +02:00
commit d5c9d97dc1
43 changed files with 343 additions and 172 deletions

View file

@ -72,11 +72,14 @@ class IniReader implements ConfigReaderInterface {
* Build and construct a new ini file parser. The parser can be used to read
* ini files that are on the filesystem.
*
* @param string $path Path to load ini config files from.
* @param string $path Path to load ini config files from. Defaults to APP . 'Config' . DS
* @param string $section Only get one section, leave null to parse and fetch
* all sections in the ini file.
*/
public function __construct($path, $section = null) {
public function __construct($path = null, $section = null) {
if (!$path) {
$path = APP . 'Config' . DS;
}
$this->_path = $path;
$this->_section = $section;
}

View file

@ -315,8 +315,11 @@ class DbConfigTask extends AppShell {
$config = array_merge($this->_defaultConfig, $config);
extract($config);
if (strpos($datasource, 'Database/') === false) {
$datasource = "Database/{$datasource}";
}
$out .= "\tpublic \${$name} = array(\n";
$out .= "\t\t'datasource' => 'Database/{$datasource}',\n";
$out .= "\t\t'datasource' => '{$datasource}',\n";
$out .= "\t\t'persistent' => {$persistent},\n";
$out .= "\t\t'host' => '{$host}',\n";

View file

@ -84,6 +84,10 @@ class ConsoleErrorHandler {
if (Configure::read('debug') == 0) {
CakeLog::write($log, $message);
}
if ($log === LOG_ERR) {
$this->_stop(1);
}
}
/**

View file

@ -160,11 +160,11 @@ class ShellDispatcher {
$errorHandler = new ConsoleErrorHandler();
if (empty($error['consoleHandler'])) {
$error['consoleHandler'] = array($errorHandler, 'handleError');
Configure::write('error', $error);
Configure::write('Error', $error);
}
if (empty($exception['consoleHandler'])) {
$exception['consoleHandler'] = array($errorHandler, 'handleException');
Configure::write('exception', $exception);
Configure::write('Exception', $exception);
}
set_exception_handler($exception['consoleHandler']);
set_error_handler($error['consoleHandler'], Configure::read('Error.level'));

View file

@ -318,10 +318,8 @@ class PhpAco {
* @return void
*/
public function build(array $allow, array $deny = array()) {
$stack = array();
$this->_tree = array();
$tree = array();
$root = &$tree;
foreach ($allow as $dotPath => $aros) {
if (is_string($aros)) {

View file

@ -327,7 +327,7 @@ class AuthComponent extends Component {
if (!empty($this->loginRedirect)) {
$default = $this->loginRedirect;
}
$controller->redirect($controller->referer($default), null, true);
$controller->redirect($controller->referer($default, true), null, true);
return false;
}

View file

@ -191,9 +191,6 @@ class CookieComponent extends Component {
$this->_expire($this->time);
$this->_values[$this->name] = array();
if (isset($_COOKIE[$this->name])) {
$this->_values[$this->name] = $this->_decrypt($_COOKIE[$this->name]);
}
}
/**

View file

@ -557,7 +557,6 @@ class Controller extends Object implements CakeEventListener {
if ($mergeParent || !empty($pluginController)) {
$appVars = get_class_vars($this->_mergeParent);
$uses = $appVars['uses'];
$merge = array('components', 'helpers');
$this->_mergeVars($merge, $this->_mergeParent, true);
}

View file

@ -198,7 +198,6 @@ class Configure {
*/
public static function delete($var = null) {
$keys = explode('.', $var);
$last = array_pop($keys);
self::$_values = Hash::remove(self::$_values, $var);
}

View file

@ -140,7 +140,10 @@ class TranslateBehavior extends ModelBehavior {
return $query;
}
$fields = array_merge($this->settings[$Model->alias], $this->runtime[$Model->alias]['fields']);
$fields = array_merge(
$this->settings[$Model->alias],
$this->runtime[$Model->alias]['fields']
);
$addFields = array();
if (empty($query['fields'])) {
$addFields = $fields;
@ -148,7 +151,11 @@ class TranslateBehavior extends ModelBehavior {
foreach ($fields as $key => $value) {
$field = (is_numeric($key)) ? $value : $key;
if (in_array($Model->escapeField('*'), $query['fields']) || in_array($Model->alias . '.' . $field, $query['fields']) || in_array($field, $query['fields'])) {
if (
in_array($Model->escapeField('*'), $query['fields']) ||
in_array($Model->alias . '.' . $field, $query['fields']) ||
in_array($field, $query['fields'])
) {
$addFields[] = $field;
}
}
@ -425,7 +432,11 @@ class TranslateBehavior extends ModelBehavior {
$conditions['locale'] = $_locale;
$conditions['content'] = $_value;
if (array_key_exists($_locale, $translations)) {
$RuntimeModel->save(array($RuntimeModel->alias => array_merge($conditions, array('id' => $translations[$_locale]))));
$RuntimeModel->save(array(
$RuntimeModel->alias => array_merge(
$conditions, array('id' => $translations[$_locale])
)
));
} else {
$RuntimeModel->save(array($RuntimeModel->alias => $conditions));
}
@ -632,7 +643,6 @@ class TranslateBehavior extends ModelBehavior {
if (is_string($fields)) {
$fields = array($fields);
}
$RuntimeModel = $this->translateModel($Model);
$associations = array();
foreach ($fields as $key => $value) {

View file

@ -447,7 +447,6 @@ class CakeSession {
*/
protected static function _configureSession() {
$sessionConfig = Configure::read('Session');
$iniSet = function_exists('ini_set');
if (isset($sessionConfig['defaults'])) {
$defaults = self::_defaultConfig($sessionConfig['defaults']);

View file

@ -150,7 +150,10 @@ class Mysql extends DboSource {
);
$this->connected = true;
} catch (PDOException $e) {
throw new MissingConnectionException(array('class' => $e->getMessage()));
throw new MissingConnectionException(array(
'class' => get_class($this),
'message' => $e->getMessage()
));
}
$this->_useAlias = (bool)version_compare($this->getVersion(), "4.1", ">=");

View file

@ -122,7 +122,10 @@ class Postgres extends DboSource {
$this->_execute('SET search_path TO ' . $config['schema']);
}
} catch (PDOException $e) {
throw new MissingConnectionException(array('class' => $e->getMessage()));
throw new MissingConnectionException(array(
'class' => get_class($this),
'message' => $e->getMessage()
));
}
return $this->connected;
@ -457,7 +460,7 @@ class Postgres extends DboSource {
)
AND c.oid = i.indrelid AND i.indexrelid = c2.oid
ORDER BY i.indisprimary DESC, i.indisunique DESC, c2.relname", false);
foreach ($indexes as $i => $info) {
foreach ($indexes as $info) {
$key = array_pop($info);
if ($key['indisprimary']) {
$key['relname'] = 'PRIMARY';

View file

@ -114,7 +114,10 @@ class Sqlite extends DboSource {
$this->_connection = new PDO('sqlite:' . $config['database'], null, null, $flags);
$this->connected = true;
} catch(PDOException $e) {
throw new MissingConnectionException(array('class' => $e->getMessage()));
throw new MissingConnectionException(array(
'class' => get_class($this),
'message' => $e->getMessage()
));
}
return $this->connected;
}
@ -488,7 +491,7 @@ class Sqlite extends DboSource {
if (is_bool($indexes)) {
return array();
}
foreach ($indexes as $i => $info) {
foreach ($indexes as $info) {
$key = array_pop($info);
$keyInfo = $this->query('PRAGMA index_info("' . $key['name'] . '")');
foreach ($keyInfo as $keyCol) {

View file

@ -130,7 +130,10 @@ class Sqlserver extends DboSource {
);
$this->connected = true;
} catch (PDOException $e) {
throw new MissingConnectionException(array('class' => $e->getMessage()));
throw new MissingConnectionException(array(
'class' => get_class($this),
'message' => $e->getMessage()
));
}
return $this->connected;

View file

@ -253,6 +253,7 @@ class DboSource extends DataSource {
if (!$this->enabled()) {
throw new MissingConnectionException(array(
'class' => get_class($this),
'message' => __d('cake_dev', 'Selected driver is not enabled'),
'enabled' => false
));
}
@ -1294,9 +1295,9 @@ class DboSource extends DataSource {
}
}
if ($type === 'hasAndBelongsToMany') {
$uniqueIds = $merge = array();
$merge = array();
foreach ($fetch as $j => $data) {
foreach ($fetch as $data) {
if (isset($data[$with]) && $data[$with][$foreignKey] === $row[$modelAlias][$modelPK]) {
if ($habtmFieldsCount <= 2) {
unset($data[$with]);
@ -1445,7 +1446,7 @@ class DboSource extends DataSource {
$data[$association] = array();
}
} else {
foreach ($merge as $i => $row) {
foreach ($merge as $row) {
$insert = array();
if (count($row) === 1) {
$insert = $row[$association];
@ -2413,7 +2414,7 @@ class DboSource extends DataSource {
}
$clauses = '/^WHERE\\x20|^GROUP\\x20BY\\x20|^HAVING\\x20|^ORDER\\x20BY\\x20/i';
if (preg_match($clauses, $conditions, $match)) {
if (preg_match($clauses, $conditions)) {
$clause = '';
}
$conditions = $this->_quoteFields($conditions);
@ -2908,7 +2909,7 @@ class DboSource extends DataSource {
$columnMap[$key] = $pdoMap[$type];
}
foreach ($values as $row => $value) {
foreach ($values as $value) {
$i = 1;
foreach ($value as $col => $val) {
$statement->bindValue($i, $val, $columnMap[$col]);
@ -3220,7 +3221,7 @@ class DboSource extends DataSource {
$isAllFloat = $isAllInt = true;
$containsFloat = $containsInt = $containsString = false;
foreach ($value as $key => $valElement) {
foreach ($value as $valElement) {
$valElement = trim($valElement);
if (!is_float($valElement) && !preg_match('/^[\d]+\.[\d]+$/', $valElement)) {
$isAllFloat = false;

View file

@ -2374,7 +2374,7 @@ class Model extends Object implements CakeEventListener {
$updateCounterCache = false;
if (!empty($this->belongsTo)) {
foreach ($this->belongsTo as $parent => $assoc) {
foreach ($this->belongsTo as $assoc) {
if (!empty($assoc['counterCache'])) {
$updateCounterCache = true;
break;
@ -2460,7 +2460,7 @@ class Model extends Object implements CakeEventListener {
* @return void
*/
protected function _deleteLinks($id) {
foreach ($this->hasAndBelongsToMany as $assoc => $data) {
foreach ($this->hasAndBelongsToMany as $data) {
list($plugin, $joinModel) = pluginSplit($data['with']);
$records = $this->{$joinModel}->find('all', array(
'conditions' => array($this->{$joinModel}->escapeField($data['foreignKey']) => $id),
@ -3053,7 +3053,7 @@ class Model extends Object implements CakeEventListener {
public function isForeignKey($field) {
$foreignKeys = array();
if (!empty($this->belongsTo)) {
foreach ($this->belongsTo as $assoc => $data) {
foreach ($this->belongsTo as $data) {
$foreignKeys[] = $data['foreignKey'];
}
}

View file

@ -18,8 +18,7 @@
* @since CakePHP(tm) v 2.2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::uses('ModelValidator', 'Model');
App::uses('CakeValidationSet', 'Model/Validator');
App::uses('Validation', 'Utility');
/**

View file

@ -18,7 +18,7 @@
* @since CakePHP(tm) v 2.2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::uses('ModelValidator', 'Model');
App::uses('CakeValidationRule', 'Model/Validator');
/**

View file

@ -675,7 +675,7 @@ class CakeRequest implements ArrayAccess {
public function accepts($type = null) {
$raw = $this->parseAccept();
$accept = array();
foreach ($raw as $value => $types) {
foreach ($raw as $types) {
$accept = array_merge($accept, $types);
}
if ($type === null) {

View file

@ -41,14 +41,31 @@ class MailTransport extends AbstractTransport {
unset($headers['To']);
$headers = $this->_headersToString($headers, $eol);
$message = implode($eol, $email->message());
if (ini_get('safe_mode') || !isset($this->_config['additionalParameters'])) {
if (!@mail($to, $email->subject(), $message, $headers)) {
throw new SocketException(__d('cake_dev', 'Could not send email.'));
}
} elseif (!@mail($to, $email->subject(), $message, $headers, $this->_config['additionalParameters'])) {
throw new SocketException(__d('cake_dev', 'Could not send email.'));
$params = null;
if (!ini_get('safe_mode')) {
$params = isset($this->_config['additionalParameters']) ? $this->_config['additionalParameters'] : null;
}
$this->_mail($to, $email->subject(), $message, $headers, $params);
return array('headers' => $headers, 'message' => $message);
}
/**
* Wraps internal function mail() and throws exception instead of errors if anything goes wrong
*
* @param string $to email's recipient
* @param string $subject email's subject
* @param string $message email's body
* @param string $headers email's custom headers
* @param string $params additional params for sending email
* @throws SocketException if mail could not be sent
* @return void
*/
protected function _mail($to, $subject, $message, $headers, $params = null) {
if (!@mail($to, $subject, $message, $headers, $params)) {
throw new SocketException(__d('cake_dev', 'Could not send email.'));
}
}
}

View file

@ -523,7 +523,7 @@ class Router {
$ext = null;
$out = array();
if ($url && strpos($url, '/') !== 0) {
if (strlen($url) && strpos($url, '/') !== 0) {
$url = '/' . $url;
}
if (strpos($url, '?') !== false) {

View file

@ -60,6 +60,23 @@ class ConsoleErrorHandlerTest extends CakeTestCase {
$this->Error->handleError(E_NOTICE, 'This is a notice error', '/some/file', 275);
}
/**
* test that the console error handler can deal with fatal errors.
*
* @return void
*/
public function testHandleFatalError() {
$content = "<error>Fatal Error Error:</error> This is a fatal error in [/some/file, line 275]\n";
ConsoleErrorHandler::$stderr->expects($this->once())->method('write')
->with($content);
$this->Error->expects($this->once())
->method('_stop')
->with(1);
$this->Error->handleError(E_USER_ERROR, 'This is a fatal error', '/some/file', 275);
}
/**
* test that the console error handler can deal with CakeExceptions.
*

View file

@ -271,12 +271,14 @@ class CookieComponentTest extends CakeTestCase {
$expected = array(
'name' => $this->Cookie->name . '[Testing]',
'value' => '[1,2,3]',
'expire' => time() + 10,
'path' => '/',
'domain' => '',
'secure' => false,
'httpOnly' => false);
$result = $this->Controller->response->cookie($this->Cookie->name . '[Testing]');
$this->assertWithinMargin($result['expire'], time() + 10, 1);
unset($result['expire']);
$this->assertEquals($expected, $result);
}

View file

@ -573,10 +573,10 @@ class ExceptionRendererTest extends CakeTestCase {
500
),
array(
new MissingConnectionException(array('class' => 'Article')),
new MissingConnectionException(array('class' => 'Mysql')),
array(
'/<h2>Missing Database Connection<\/h2>/',
'/Article requires a database connection/'
'/A Database connection using "Mysql" was missing or unable to connect./',
),
500
),
@ -584,7 +584,7 @@ class ExceptionRendererTest extends CakeTestCase {
new MissingConnectionException(array('class' => 'Mysql', 'enabled' => false)),
array(
'/<h2>Missing Database Connection<\/h2>/',
'/Mysql requires a database connection/',
'/A Database connection using "Mysql" was missing or unable to connect./',
'/Mysql driver is NOT enabled/'
),
500

View file

@ -0,0 +1,84 @@
<?php
/**
* MailTransportTest file
*
* PHP 5
*
* CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
* @package Cake.Test.Case.Network.Email
* @since CakePHP(tm) v 2.0.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::uses('CakeEmail', 'Network/Email');
App::uses('AbstractTransport', 'Network/Email');
App::uses('MailTransport', 'Network/Email');
/**
* Test case
*
*/
class MailTransportTest extends CakeTestCase {
/**
* Setup
*
* @return void
*/
public function setUp() {
$this->MailTransport = $this->getMock('MailTransport', array('_mail'));
$this->MailTransport->config(array('additionalParameters' => '-f'));
}
/**
* testSend method
*
* @return void
*/
public function testSendData() {
$email = $this->getMock('CakeEmail', array('message'), array());
$email->from('noreply@cakephp.org', 'CakePHP Test');
$email->returnPath('pleasereply@cakephp.org', 'CakePHP Return');
$email->to('cake@cakephp.org', 'CakePHP');
$email->cc(array('mark@cakephp.org' => 'Mark Story', 'juan@cakephp.org' => 'Juan Basso'));
$email->bcc('phpnut@cakephp.org');
$email->messageID('<4d9946cf-0a44-4907-88fe-1d0ccbdd56cb@localhost>');
$email->subject('Foø Bår Béz Foø Bår Béz Foø Bår Béz Foø Bår Béz');
$date = date(DATE_RFC2822);
$email->setHeaders(array('X-Mailer' => 'CakePHP Email', 'Date' => $date));
$email->expects($this->any())->method('message')->will($this->returnValue(array('First Line', 'Second Line', '.Third Line', '')));
$data = "From: CakePHP Test <noreply@cakephp.org>" . PHP_EOL;
$data .= "Return-Path: CakePHP Return <pleasereply@cakephp.org>" . PHP_EOL;
$data .= "Cc: Mark Story <mark@cakephp.org>, Juan Basso <juan@cakephp.org>" . PHP_EOL;
$data .= "Bcc: phpnut@cakephp.org" . PHP_EOL;
$data .= "X-Mailer: CakePHP Email" . PHP_EOL;
$data .= "Date: " . $date . PHP_EOL;
$data .= "Message-ID: <4d9946cf-0a44-4907-88fe-1d0ccbdd56cb@localhost>" . PHP_EOL;
$data .= "MIME-Version: 1.0" . PHP_EOL;
$data .= "Content-Type: text/plain; charset=UTF-8" . PHP_EOL;
$data .= "Content-Transfer-Encoding: 8bit";
$subject = '=?UTF-8?B?Rm/DuCBCw6VyIELDqXogRm/DuCBCw6VyIELDqXogRm/DuCBCw6VyIELDqXog?=';
$subject .= "\r\n" . ' =?UTF-8?B?Rm/DuCBCw6VyIELDqXo=?=';
$this->MailTransport->expects($this->once())->method('_mail')
->with(
'CakePHP <cake@cakephp.org>',
$subject,
implode(PHP_EOL, array('First Line', 'Second Line', '.Third Line', '')),
$data,
'-f'
);
$this->MailTransport->send($email);
}
}

View file

@ -451,6 +451,30 @@ class RouterTest extends CakeTestCase {
$this->assertEquals($expected, $result);
}
/**
* Test that catch all routes work with a variety of falsey inputs.
*
* @return void
*/
public function testUrlCatchAllRoute() {
Router::connect('/*', array('controller' => 'categories', 'action' => 'index'));
$result = Router::url(array('controller' => 'categories', 'action' => 'index', '0'));
$this->assertEquals('/0', $result);
$expected = array(
'plugin' => null,
'controller' => 'categories',
'action' => 'index',
'pass' => array('0'),
'named' => array()
);
$result = Router::parse('/0');
$this->assertEquals($expected, $result);
$result = Router::parse('0');
$this->assertEquals($expected, $result);
}
/**
* Tests using arrays in named parameters
*

View file

@ -1049,4 +1049,19 @@ class CakeTimeTest extends CakeTestCase {
}
}
/**
* Tests that using CakeTime::format() with the correct sytax actually converts
* from one timezone to the other correctly
*
* @return void
**/
public function testCorrectTimezoneConversion() {
date_default_timezone_set('UTC');
$date = '2012-01-01 10:00:00';
$converted = CakeTime::format($date, '%Y-%m-%d %H:%M:%S', '', 'Europe/Copenhagen');
$expected = new DateTime($date);
$expected->setTimezone(new DateTimeZone('Europe/Copenhagen'));
$this->assertEquals($expected->format('Y-m-d H:i:s'), $converted);
}
}

View file

@ -268,7 +268,7 @@ class DebuggerTest extends CakeTestCase {
* Test method for testing addFormat with callbacks.
*/
public function customFormat($error, $strings) {
return $error['error'] . ': I eated an error ' . $error['path'];
return $error['error'] . ': I eated an error ' . $error['file'];
}
/**

View file

@ -362,11 +362,10 @@ class FileTest extends CakeTestCase {
* @return void
*/
public function testLastAccess() {
$ts = time();
$someFile = new File(TMP . 'some_file.txt', false);
$this->assertFalse($someFile->lastAccess());
$this->assertTrue($someFile->open());
$this->assertTrue($someFile->lastAccess() >= $ts);
$this->assertWithinMargin($someFile->lastAccess(), time(), 2);
$someFile->close();
$someFile->delete();
}
@ -377,13 +376,14 @@ class FileTest extends CakeTestCase {
* @return void
*/
public function testLastChange() {
$ts = time();
$someFile = new File(TMP . 'some_file.txt', false);
$this->assertFalse($someFile->lastChange());
$this->assertTrue($someFile->open('r+'));
$this->assertTrue($someFile->lastChange() >= $ts);
$this->assertWithinMargin($someFile->lastChange(), time(), 2);
$someFile->write('something');
$this->assertTrue($someFile->lastChange() >= $ts);
$this->assertWithinMargin($someFile->lastChange(), time(), 2);
$someFile->close();
$someFile->delete();
}

View file

@ -107,8 +107,7 @@ class Contact extends CakeTestModel {
'imrequiredonupdate' => array('notEmpty' => array('rule' => 'alphaNumeric', 'on' => 'update')),
'imrequiredoncreate' => array('required' => array('rule' => 'alphaNumeric', 'on' => 'create')),
'imrequiredonboth' => array(
'required' => array('rule' => 'alphaNumeric', 'allowEmpty' => true),
'check' => array('rule' => 'alphaNumeric')
'required' => array('rule' => 'alphaNumeric'),
),
'string_required' => 'notEmpty',
'imalsorequired' => array('rule' => 'alphaNumeric', 'allowEmpty' => false),
@ -3274,80 +3273,6 @@ class FormHelperTest extends CakeTestCase {
);
$this->assertTags($result, $expected);
$result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => '1'));
$expected = array(
'fieldset' => array(),
'legend' => array(),
'Field',
'/legend',
array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '1', 'id' => 'ModelField1', 'checked' => 'checked')),
array('label' => array('for' => 'ModelField1')),
'Yes',
'/label',
array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '0', 'id' => 'ModelField0')),
array('label' => array('for' => 'ModelField0')),
'No',
'/label',
'/fieldset'
);
$this->assertTags($result, $expected);
$result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => '0'));
$expected = array(
'fieldset' => array(),
'legend' => array(),
'Field',
'/legend',
array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '1', 'id' => 'ModelField1')),
array('label' => array('for' => 'ModelField1')),
'Yes',
'/label',
array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '0', 'id' => 'ModelField0', 'checked' => 'checked')),
array('label' => array('for' => 'ModelField0')),
'No',
'/label',
'/fieldset'
);
$this->assertTags($result, $expected);
$result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => null));
$expected = array(
'fieldset' => array(),
'legend' => array(),
'Field',
'/legend',
'input' => array('type' => 'hidden', 'name' => 'data[Model][field]', 'value' => '', 'id' => 'ModelField_'),
array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '1', 'id' => 'ModelField1')),
array('label' => array('for' => 'ModelField1')),
'Yes',
'/label',
array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '0', 'id' => 'ModelField0')),
array('label' => array('for' => 'ModelField0')),
'No',
'/label',
'/fieldset'
);
$this->assertTags($result, $expected);
$result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'));
$expected = array(
'fieldset' => array(),
'legend' => array(),
'Field',
'/legend',
'input' => array('type' => 'hidden', 'name' => 'data[Model][field]', 'value' => '', 'id' => 'ModelField_'),
array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '1', 'id' => 'ModelField1')),
array('label' => array('for' => 'ModelField1')),
'Yes',
'/label',
array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '0', 'id' => 'ModelField0')),
array('label' => array('for' => 'ModelField0')),
'No',
'/label',
'/fieldset'
);
$this->assertTags($result, $expected);
$result = $this->Form->input('Newsletter.subscribe', array('legend' => 'Legend title', 'type' => 'radio', 'options' => array('0' => 'Unsubscribe', '1' => 'Subscribe')));
$expected = array(
'div' => array('class' => 'input radio'),
@ -3536,6 +3461,59 @@ class FormHelperTest extends CakeTestCase {
$this->assertTags($result, $expected);
}
/**
* Test that radios with a 0 value are selected under the correct conditions.
*
* @return void
*/
public function testRadioOptionWithZeroValue() {
$expected = array(
'fieldset' => array(),
'legend' => array(),
'Field',
'/legend',
array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '1', 'id' => 'ModelField1')),
array('label' => array('for' => 'ModelField1')),
'Yes',
'/label',
array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '0', 'id' => 'ModelField0', 'checked' => 'checked')),
array('label' => array('for' => 'ModelField0')),
'No',
'/label',
'/fieldset'
);
$result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => '0'));
$this->assertTags($result, $expected);
$result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => 0));
$this->assertTags($result, $expected);
$expected = array(
'fieldset' => array(),
'legend' => array(),
'Field',
'/legend',
'input' => array('type' => 'hidden', 'name' => 'data[Model][field]', 'value' => '', 'id' => 'ModelField_'),
array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '1', 'id' => 'ModelField1')),
array('label' => array('for' => 'ModelField1')),
'Yes',
'/label',
array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '0', 'id' => 'ModelField0')),
array('label' => array('for' => 'ModelField0')),
'No',
'/label',
'/fieldset'
);
$result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => null));
$this->assertTags($result, $expected);
$result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'), array('value' => ''));
$this->assertTags($result, $expected);
$result = $this->Form->radio('Model.field', array('1' => 'Yes', '0' => 'No'));
$this->assertTags($result, $expected);
}
/**
* test disabled radio options
*
@ -3545,7 +3523,7 @@ class FormHelperTest extends CakeTestCase {
$result = $this->Form->radio(
'Model.field',
array('option A', 'option B'),
array('disabled' => array('option A'), 'value' => 'option A')
array('disabled' => array('option A'), 'value' => '0')
);
$expected = array(
'fieldset' => array(),
@ -3567,7 +3545,7 @@ class FormHelperTest extends CakeTestCase {
$result = $this->Form->radio(
'Model.field',
array('option A', 'option B'),
array('disabled' => true, 'value' => 'option A')
array('disabled' => true, 'value' => '0')
);
$expected = array(
'fieldset' => array(),
@ -3589,7 +3567,7 @@ class FormHelperTest extends CakeTestCase {
$result = $this->Form->radio(
'Model.field',
array('option A', 'option B'),
array('disabled' => 'disabled', 'value' => 'option A')
array('disabled' => 'disabled', 'value' => '0')
);
$expected = array(
'fieldset' => array(),
@ -4346,6 +4324,23 @@ class FormHelperTest extends CakeTestCase {
$this->assertRegExp('/"' . $key . '"/', $result);
}
/**
* Multiple select elements should always be secured as they always participate
* in the POST data.
*
* @return void
*/
public function testSelectMultipleSecureWithNoOptions() {
$this->Form->request['_Token'] = array('key' => 'testkey');
$this->assertEquals(array(), $this->Form->fields);
$result = $this->Form->select(
'Model.select',
array(),
array('multiple' => true)
);
$this->assertEquals(array('Model.select'), $this->Form->fields);
}
/**
* When a select box has no options it should not be added to the fields list
* as it always fail post validation.

View file

@ -941,18 +941,11 @@ class CakeTime {
* @see CakeTime::i18nFormat()
*/
public static function format($date, $format = null, $default = false, $timezone = null) {
//Backwards compatible params order
//Backwards compatible params re-order test
$time = self::fromString($format, $timezone);
$_time = false;
if (!is_numeric($time)) {
$_time = self::fromString($date, $timezone);
}
if (is_numeric($_time) && $time === false) {
return self::i18nFormat($_time, $format, $default, $timezone);
}
if ($time === false && $default !== false) {
return $default;
if ($time === false) {
return self::i18nFormat($date, $format, $default, $timezone);
}
return date($date, $time);
}

View file

@ -213,7 +213,6 @@ class Debugger {
if (empty($line)) {
$line = '??';
}
$path = self::trimPath($file);
$info = compact('code', 'description', 'file', 'line');
if (!in_array($info, $self->errors)) {

View file

@ -391,7 +391,7 @@ class Folder {
$paths = $this->tree($path);
foreach ($paths as $type) {
foreach ($type as $key => $fullpath) {
foreach ($type as $fullpath) {
$check = explode(DS, $fullpath);
$count = count($check);

View file

@ -432,7 +432,6 @@ class Hash {
}
$stack = array();
$i = 1;
while (!empty($needle)) {
$key = key($needle);
$val = $needle[$key];

View file

@ -19,7 +19,13 @@
<h2><?php echo __d('cake_dev', 'Missing Database Connection'); ?></h2>
<p class="error">
<strong><?php echo __d('cake_dev', 'Error'); ?>: </strong>
<?php echo __d('cake_dev', '%s requires a database connection', $class); ?>
<?php echo __d('cake_dev', 'A Database connection using "%s" was missing or unable to connect. ', $class); ?>
<br />
<?php
if (isset($message)):
echo __d('cake_dev', 'The database server returned this error: %s', $message);
endif;
?>
</p>
<?php if (!$enabled) : ?>
<p class="error">

View file

@ -168,14 +168,14 @@ class FormHelper extends AppHelper {
*
* The $key parameter accepts the following list of values:
*
* - key: Returns the name of the primary key for the model
* - fields: Returns the model schema
* - validates: returns the list of fields that are required
* - errors: returns the list of validation errors
* - key: Returns the name of the primary key for the model
* - fields: Returns the model schema
* - validates: returns the list of fields that are required
* - errors: returns the list of validation errors
*
* If the $field parameter is passed if will return the information for that sole field.
*
* `$this->_introspectModel('Post', 'fields', 'title');` will return the schema information for title column
* `$this->_introspectModel('Post', 'fields', 'title');` will return the schema information for title column
*
* @param string $model name of the model to extract information from
* @param string $key name of the special information key to obtain (key, fields, validates, errors)
@ -194,7 +194,7 @@ class FormHelper extends AppHelper {
if ($key === 'fields') {
if (!isset($this->fieldset[$model]['fields'])) {
$fields = $this->fieldset[$model]['fields'] = $object->schema();
$this->fieldset[$model]['fields'] = $object->schema();
foreach ($object->hasAndBelongsToMany as $alias => $assocData) {
$this->fieldset[$object->alias]['fields'][$alias] = array('type' => 'multiple');
}
@ -244,20 +244,23 @@ class FormHelper extends AppHelper {
* @return boolean true if field is required to be filled, false otherwise
*/
protected function _isRequiredField($validationRules) {
if (empty($validationRules) || count($validationRules) === 0) {
return false;
}
foreach ($validationRules as $rule) {
$rule->isUpdate($this->requestType === 'put');
if (!$rule->isEmptyAllowed()) {
return true;
if ($rule->isEmptyAllowed()) {
return false;
}
}
return false;
return true;
}
/**
* Returns false if given form field described by the current entity has no errors.
* Otherwise it returns the validation message
*
* @return mixed Either false when there or no errors, or an array of error
* @return mixed Either false when there are no errors, or an array of error
* strings. An error string could be ''.
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::tagIsInvalid
*/
@ -320,7 +323,6 @@ class FormHelper extends AppHelper {
$key = null;
if ($model !== false) {
$object = $this->_getModel($model);
$key = $this->_introspectModel($model, 'key');
$this->setEntity($model, true);
}
@ -717,7 +719,7 @@ class FormHelper extends AppHelper {
/**
* Returns a formatted LABEL element for HTML FORMs. Will automatically generate
* a for attribute if one is not provided.
* a `for` attribute if one is not provided.
*
* ### Options
*
@ -1375,7 +1377,7 @@ class FormHelper extends AppHelper {
foreach ($options as $optValue => $optTitle) {
$optionsHere = array('value' => $optValue);
if (isset($value) && $optValue == $value) {
if (isset($value) && strval($optValue) === strval($value)) {
$optionsHere['checked'] = 'checked';
}
if ($disabled && (!is_array($disabled) || in_array($optValue, $disabled))) {
@ -1864,10 +1866,12 @@ class FormHelper extends AppHelper {
if (!empty($tag) || isset($template)) {
$hasOptions = (count($options) > 0 || $showEmpty);
// Secure the field if there are options, or its a multi select.
// Single selects with no options don't submit, but multiselects do.
if (
(!isset($secure) || $secure == true) &&
empty($attributes['disabled']) &&
$hasOptions
(!empty($attributes['multiple']) || $hasOptions)
) {
$this->_secure(true);
}

View file

@ -254,7 +254,6 @@ class MootoolsEngineHelper extends JsBaseEngineHelper {
$options['url'] = $url;
$options = $this->_prepareCallbacks('request', $options);
if (!empty($options['dataExpression'])) {
$callbacks[] = 'data';
unset($options['dataExpression']);
} elseif (!empty($data)) {
$data = $this->object($data);

View file

@ -471,7 +471,7 @@ class PaginatorHelper extends AppHelper {
$url = array_merge(array('page' => $paging['page'] + ($which == 'Prev' ? $step * -1 : $step)), $url);
if ($this->{$check}($model)) {
return $this->Html->tag($tag, $this->link($title, $url, array_merge($options, compact('escape'))), compact('class'));
return $this->Html->tag($tag, $this->link($title, $url, array_merge($options, compact('escape', 'model'))), compact('class'));
} else {
unset($options['rel']);
return $this->Html->tag($tag, $title, array_merge($options, compact('escape', 'class')));

View file

@ -237,7 +237,6 @@ class PrototypeEngineHelper extends JsBaseEngineHelper {
$url = '"' . $this->url($url) . '"';
$options = $this->_mapOptions('request', $options);
$type = '.Request';
$data = null;
if (isset($options['type']) && strtolower($options['type']) == 'json') {
unset($options['type']);
}

View file

@ -341,7 +341,7 @@ class RssHelper extends AppHelper {
$nodes->item(0)->setAttribute($key, $value);
}
}
foreach ($children as $k => $child) {
foreach ($children as $child) {
$child = $elem->createElement($name, $child);
$nodes->item(0)->appendChild($child);
}

View file

@ -358,7 +358,6 @@ class TimeHelper extends AppHelper {
*/
public function timeAgoInWords($dateTime, $options = array()) {
$element = null;
$stringDate = '';
if (is_array($options) && !empty($options['element'])) {
$element = array(

View file

@ -297,11 +297,6 @@ class View extends Object {
*/
protected $_eventManager = null;
/**
* The view file to be rendered, only used inside _execute()
*/
private $__viewFileName = null;
/**
* Whether the event manager was already configured for this object
*
@ -830,7 +825,7 @@ class View extends Object {
*/
public function loadHelpers() {
$helpers = HelperCollection::normalizeObjectArray($this->helpers);
foreach ($helpers as $name => $properties) {
foreach ($helpers as $properties) {
list($plugin, $class) = pluginSplit($properties['class']);
$this->{$class} = $this->Helpers->load($properties['class'], $properties['settings']);
}