Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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
  • Loading branch information...
commit d5c9d97dc19a2614b1d653a63e4ba7060847d7b6 2 parents e454282 + 6818d69
@lorenzo lorenzo authored
Showing with 343 additions and 172 deletions.
  1. +5 −2 lib/Cake/Configure/IniReader.php
  2. +4 −1 lib/Cake/Console/Command/Task/DbConfigTask.php
  3. +4 −0 lib/Cake/Console/ConsoleErrorHandler.php
  4. +2 −2 lib/Cake/Console/ShellDispatcher.php
  5. +0 −2  lib/Cake/Controller/Component/Acl/PhpAcl.php
  6. +1 −1  lib/Cake/Controller/Component/AuthComponent.php
  7. +0 −3  lib/Cake/Controller/Component/CookieComponent.php
  8. +0 −1  lib/Cake/Controller/Controller.php
  9. +0 −1  lib/Cake/Core/Configure.php
  10. +14 −4 lib/Cake/Model/Behavior/TranslateBehavior.php
  11. +0 −1  lib/Cake/Model/Datasource/CakeSession.php
  12. +4 −1 lib/Cake/Model/Datasource/Database/Mysql.php
  13. +5 −2 lib/Cake/Model/Datasource/Database/Postgres.php
  14. +5 −2 lib/Cake/Model/Datasource/Database/Sqlite.php
  15. +4 −1 lib/Cake/Model/Datasource/Database/Sqlserver.php
  16. +7 −6 lib/Cake/Model/Datasource/DboSource.php
  17. +3 −3 lib/Cake/Model/Model.php
  18. +1 −2  lib/Cake/Model/Validator/CakeValidationRule.php
  19. +1 −1  lib/Cake/Model/Validator/CakeValidationSet.php
  20. +1 −1  lib/Cake/Network/CakeRequest.php
  21. +23 −6 lib/Cake/Network/Email/MailTransport.php
  22. +1 −1  lib/Cake/Routing/Router.php
  23. +17 −0 lib/Cake/Test/Case/Console/ConsoleErrorHandlerTest.php
  24. +3 −1 lib/Cake/Test/Case/Controller/Component/CookieComponentTest.php
  25. +3 −3 lib/Cake/Test/Case/Error/ExceptionRendererTest.php
  26. +84 −0 lib/Cake/Test/Case/Network/Email/MailTransportTest.php
  27. +24 −0 lib/Cake/Test/Case/Routing/RouterTest.php
  28. +15 −0 lib/Cake/Test/Case/Utility/CakeTimeTest.php
  29. +1 −1  lib/Cake/Test/Case/Utility/DebuggerTest.php
  30. +5 −5 lib/Cake/Test/Case/Utility/FileTest.php
  31. +74 −79 lib/Cake/Test/Case/View/Helper/FormHelperTest.php
  32. +3 −10 lib/Cake/Utility/CakeTime.php
  33. +0 −1  lib/Cake/Utility/Debugger.php
  34. +1 −1  lib/Cake/Utility/Folder.php
  35. +0 −1  lib/Cake/Utility/Hash.php
  36. +7 −1 lib/Cake/View/Errors/missing_connection.ctp
  37. +18 −14 lib/Cake/View/Helper/FormHelper.php
  38. +0 −1  lib/Cake/View/Helper/MootoolsEngineHelper.php
  39. +1 −1  lib/Cake/View/Helper/PaginatorHelper.php
  40. +0 −1  lib/Cake/View/Helper/PrototypeEngineHelper.php
  41. +1 −1  lib/Cake/View/Helper/RssHelper.php
  42. +0 −1  lib/Cake/View/Helper/TimeHelper.php
  43. +1 −6 lib/Cake/View/View.php
View
7 lib/Cake/Configure/IniReader.php
@@ -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
5 lib/Cake/Console/Command/Task/DbConfigTask.php
@@ -315,8 +315,11 @@ public function bake($configs) {
$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
4 lib/Cake/Console/ConsoleErrorHandler.php
@@ -84,6 +84,10 @@ public function handleError($code, $description, $file = null, $line = null, $co
if (Configure::read('debug') == 0) {
CakeLog::write($log, $message);
}
+
+ if ($log === LOG_ERR) {
+ $this->_stop(1);
+ }
}
/**
View
4 lib/Cake/Console/ShellDispatcher.php
@@ -160,11 +160,11 @@ public function setErrorHandlers() {
$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
2  lib/Cake/Controller/Component/Acl/PhpAcl.php
@@ -318,10 +318,8 @@ public function resolve($aco) {
* @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
2  lib/Cake/Controller/Component/AuthComponent.php
@@ -327,7 +327,7 @@ public function startup(Controller $controller) {
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
3  lib/Cake/Controller/Component/CookieComponent.php
@@ -191,9 +191,6 @@ public function startup(Controller $controller) {
$this->_expire($this->time);
$this->_values[$this->name] = array();
- if (isset($_COOKIE[$this->name])) {
- $this->_values[$this->name] = $this->_decrypt($_COOKIE[$this->name]);
- }
}
/**
View
1  lib/Cake/Controller/Controller.php
@@ -557,7 +557,6 @@ protected function _mergeControllerVars() {
if ($mergeParent || !empty($pluginController)) {
$appVars = get_class_vars($this->_mergeParent);
- $uses = $appVars['uses'];
$merge = array('components', 'helpers');
$this->_mergeVars($merge, $this->_mergeParent, true);
}
View
1  lib/Cake/Core/Configure.php
@@ -198,7 +198,6 @@ public static function check($var = null) {
*/
public static function delete($var = null) {
$keys = explode('.', $var);
- $last = array_pop($keys);
self::$_values = Hash::remove(self::$_values, $var);
}
View
18 lib/Cake/Model/Behavior/TranslateBehavior.php
@@ -140,7 +140,10 @@ public function beforeFind(Model $Model, $query) {
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 @@ public function beforeFind(Model $Model, $query) {
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 @@ public function afterSave(Model $Model, $created) {
$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 @@ public function unbindTranslation(Model $Model, $fields = null) {
if (is_string($fields)) {
$fields = array($fields);
}
- $RuntimeModel = $this->translateModel($Model);
$associations = array();
foreach ($fields as $key => $value) {
View
1  lib/Cake/Model/Datasource/CakeSession.php
@@ -447,7 +447,6 @@ public static function clear() {
*/
protected static function _configureSession() {
$sessionConfig = Configure::read('Session');
- $iniSet = function_exists('ini_set');
if (isset($sessionConfig['defaults'])) {
$defaults = self::_defaultConfig($sessionConfig['defaults']);
View
5 lib/Cake/Model/Datasource/Database/Mysql.php
@@ -150,7 +150,10 @@ public function connect() {
);
$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
7 lib/Cake/Model/Datasource/Database/Postgres.php
@@ -122,7 +122,10 @@ public function connect() {
$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 @@ public function index($model) {
)
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
7 lib/Cake/Model/Datasource/Database/Sqlite.php
@@ -114,7 +114,10 @@ public function connect() {
$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 @@ public function index($model) {
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
5 lib/Cake/Model/Datasource/Database/Sqlserver.php
@@ -130,7 +130,10 @@ public function connect() {
);
$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
13 lib/Cake/Model/Datasource/DboSource.php
@@ -253,6 +253,7 @@ public function __construct($config = null, $autoConnect = true) {
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 @@ public function queryAssociation(Model $model, &$linkModel, $type, $association,
}
}
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 @@ protected function _mergeAssociation(&$data, &$merge, $association, $type, $self
$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 @@ public function conditions($conditions, $quoteValues = true, $where = true, $mod
}
$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 @@ public function insertMulti($table, $fields, $values) {
$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 @@ public function introspectType($value) {
$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
6 lib/Cake/Model/Model.php
@@ -2374,7 +2374,7 @@ public function delete($id = null, $cascade = true) {
$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 @@ protected function _deleteDependent($id, $cascade) {
* @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 @@ public function invalidate($field, $value = true) {
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
3  lib/Cake/Model/Validator/CakeValidationRule.php
@@ -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
2  lib/Cake/Model/Validator/CakeValidationSet.php
@@ -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
2  lib/Cake/Network/CakeRequest.php
@@ -675,7 +675,7 @@ public function subdomains($tldLength = 1) {
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
29 lib/Cake/Network/Email/MailTransport.php
@@ -41,14 +41,31 @@ public function send(CakeEmail $email) {
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
2  lib/Cake/Routing/Router.php
@@ -523,7 +523,7 @@ public static function parse($url) {
$ext = null;
$out = array();
- if ($url && strpos($url, '/') !== 0) {
+ if (strlen($url) && strpos($url, '/') !== 0) {
$url = '/' . $url;
}
if (strpos($url, '?') !== false) {
View
17 lib/Cake/Test/Case/Console/ConsoleErrorHandlerTest.php
@@ -61,6 +61,23 @@ public function testHandleError() {
}
/**
+ * 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.
*
* @return void
View
4 lib/Cake/Test/Case/Controller/Component/CookieComponentTest.php
@@ -271,12 +271,14 @@ public function testWriteArrayValues() {
$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
6 lib/Cake/Test/Case/Error/ExceptionRendererTest.php
@@ -573,10 +573,10 @@ public static function testProvider() {
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 @@ public static function testProvider() {
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
84 lib/Cake/Test/Case/Network/Email/MailTransportTest.php
@@ -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
24 lib/Cake/Test/Case/Routing/RouterTest.php
@@ -452,6 +452,30 @@ public function testUrlGenerationBasic() {
}
/**
+ * 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
*
* @return void
View
15 lib/Cake/Test/Case/Utility/CakeTimeTest.php
@@ -1049,4 +1049,19 @@ public function testListTimezones() {
}
}
+/**
+ * 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
2  lib/Cake/Test/Case/Utility/DebuggerTest.php
@@ -268,7 +268,7 @@ public function testAddFormatCallback() {
* 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
10 lib/Cake/Test/Case/Utility/FileTest.php
@@ -362,11 +362,10 @@ public function testExecutable() {
* @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 @@ public function testLastAccess() {
* @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
153 lib/Cake/Test/Case/View/Helper/FormHelperTest.php
@@ -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 @@ public function testRadio() {
);
$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'),
@@ -3537,6 +3462,59 @@ public function testRadio() {
}
/**
+ * 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
*
* @return void
@@ -3545,7 +3523,7 @@ public function testRadioDisabled() {
$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 @@ public function testRadioDisabled() {
$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 @@ public function testRadioDisabled() {
$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(),
@@ -4347,6 +4325,23 @@ public function testSelectMultipleCheckboxSecurity() {
}
/**
+ * 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
13 lib/Cake/Utility/CakeTime.php
@@ -941,18 +941,11 @@ public static function gmt($dateString = null) {
* @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
1  lib/Cake/Utility/Debugger.php
@@ -213,7 +213,6 @@ public static function showError($code, $description, $file = null, $line = null
if (empty($line)) {
$line = '??';
}
- $path = self::trimPath($file);
$info = compact('code', 'description', 'file', 'line');
if (!in_array($info, $self->errors)) {
View
2  lib/Cake/Utility/Folder.php
@@ -391,7 +391,7 @@ public function chmod($path, $mode = false, $recursive = true, $exceptions = arr
$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
1  lib/Cake/Utility/Hash.php
@@ -432,7 +432,6 @@ public static function contains(array $data, array $needle) {
}
$stack = array();
- $i = 1;
while (!empty($needle)) {
$key = key($needle);
$val = $needle[$key];
View
8 lib/Cake/View/Errors/missing_connection.ctp
@@ -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
32 lib/Cake/View/Helper/FormHelper.php
@@ -168,14 +168,14 @@ protected function _getModel($model) {
*
* 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 @@ protected function _introspectModel($model, $key, $field = null) {
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 @@ protected function _introspectModel($model, $key, $field = null) {
* @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 @@ public function create($model = null, $options = array()) {
$key = null;
if ($model !== false) {
- $object = $this->_getModel($model);
$key = $this->_introspectModel($model, 'key');
$this->setEntity($model, true);
}
@@ -717,7 +719,7 @@ public function error($field, $text = null, $options = array()) {
/**
* 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 @@ public function radio($fieldName, $options = array(), $attributes = array()) {
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 @@ public function select($fieldName, $options = array(), $attributes = array()) {
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
1  lib/Cake/View/Helper/MootoolsEngineHelper.php
@@ -254,7 +254,6 @@ public function request($url, $options = array()) {
$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
2  lib/Cake/View/Helper/PaginatorHelper.php
@@ -471,7 +471,7 @@ protected function _pagingLink($which, $title = null, $options = array(), $disab
$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
1  lib/Cake/View/Helper/PrototypeEngineHelper.php
@@ -237,7 +237,6 @@ public function request($url, $options = array()) {
$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
2  lib/Cake/View/Helper/RssHelper.php
@@ -341,7 +341,7 @@ public function elem($name, $attrib = array(), $content = null, $endTag = true)
$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
1  lib/Cake/View/Helper/TimeHelper.php
@@ -358,7 +358,6 @@ public function toRSS($dateString, $timezone = null) {
*/
public function timeAgoInWords($dateTime, $options = array()) {
$element = null;
- $stringDate = '';
if (is_array($options) && !empty($options['element'])) {
$element = array(
View
7 lib/Cake/View/View.php
@@ -298,11 +298,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
*
* @var boolean
@@ -830,7 +825,7 @@ public function __isset($name) {
*/
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']);
}
Please sign in to comment.
Something went wrong with that request. Please try again.