Merge branch '2.0-request' of github.com:cakephp/cakephp into 2.0-request

Conflicts:
	cake/libs/controller/components/auth.php
This commit is contained in:
mark_story 2010-07-31 11:08:20 -04:00
commit d0feaf8985
32 changed files with 700 additions and 75 deletions

View file

@ -18,5 +18,5 @@
// @license MIT License (http://www.opensource.org/licenses/mit-license.php)
// +--------------------------------------------------------------------------------------------+ //
////////////////////////////////////////////////////////////////////////////////////////////////////
1.3.2
1.3.3

View file

@ -17,4 +17,4 @@
* @since CakePHP(tm) v 1.1.11.4062
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
return $config['Cake.version'] = '1.3.2';
return $config['Cake.version'] = '1.3.3';

View file

@ -88,6 +88,9 @@ class SchemaShell extends Shell {
}
if (!empty($this->params['plugin'])) {
$plugin = $this->params['plugin'];
if (empty($name)) {
$name = $plugin;
}
}
$this->Schema =& new CakeSchema(compact('name', 'path', 'file', 'connection', 'plugin'));
}

View file

@ -171,7 +171,7 @@ class Shell extends Object {
}
/**
* Starts up the the Shell
* Starts up the Shell
* allows for checking and configuring prior to command or main execution
* can be overriden in subclasses
*

View file

@ -376,7 +376,8 @@ class Dispatcher {
*/
protected function _deliverAsset($assetFile, $ext) {
$ob = @ini_get("zlib.output_compression") !== '1' && extension_loaded("zlib") && (strpos(env('HTTP_ACCEPT_ENCODING'), 'gzip') !== false);
if ($ob && Configure::read('Asset.compress')) {
$compressionEnabled = $ob && Configure::read('Asset.compress');
if ($compressionEnabled) {
ob_start();
ob_start('ob_gzhandler');
}
@ -403,11 +404,13 @@ class Dispatcher {
if ($ext === 'css' || $ext === 'js') {
include($assetFile);
} else {
ob_clean();
if ($compressionEnabled) {
ob_clean();
}
readfile($assetFile);
}
if (Configure::read('Asset.compress')) {
if ($compressionEnabled) {
ob_end_flush();
}
}

View file

@ -270,6 +270,12 @@ class Cache {
$success = self::$_engines[$config]->write($settings['prefix'] . $key, $value, $settings['duration']);
self::set();
if ($success === false) {
trigger_error(
sprintf(__("%s cache was unable to write '%s' to cache", true), $config, $key),
E_USER_WARNING
);
}
return $success;
}

268
cake/libs/cake_response.php Normal file
View file

@ -0,0 +1,268 @@
<?php
/**
* A class reposible for managing the response text, status and headers of a HTTP response
*
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package cake
* @subpackage cake.cake.libs
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
class CakeResponse {
/**
* Holds HTTP response statuses
*
* @var array
*/
protected $_statusCodes = array(
100 => 'Continue',
101 => 'Switching Protocols',
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found',
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
307 => 'Temporary Redirect',
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Time-out',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Large',
415 => 'Unsupported Media Type',
416 => 'Requested range not satisfiable',
417 => 'Expectation Failed',
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Time-out'
);
/**
* Holds known mime type mappings
*
* @var array
*/
protected $_mimeTypes = array(
'ai' => 'application/postscript', 'bcpio' => 'application/x-bcpio', 'bin' => 'application/octet-stream',
'ccad' => 'application/clariscad', 'cdf' => 'application/x-netcdf', 'class' => 'application/octet-stream',
'cpio' => 'application/x-cpio', 'cpt' => 'application/mac-compactpro', 'csh' => 'application/x-csh',
'csv' => 'application/csv', 'dcr' => 'application/x-director', 'dir' => 'application/x-director',
'dms' => 'application/octet-stream', 'doc' => 'application/msword', 'drw' => 'application/drafting',
'dvi' => 'application/x-dvi', 'dwg' => 'application/acad', 'dxf' => 'application/dxf',
'dxr' => 'application/x-director', 'eot' => 'application/vnd.ms-fontobject', 'eps' => 'application/postscript',
'exe' => 'application/octet-stream', 'ez' => 'application/andrew-inset',
'flv' => 'video/x-flv', 'gtar' => 'application/x-gtar', 'gz' => 'application/x-gzip',
'bz2' => 'application/x-bzip', '7z' => 'application/x-7z-compressed', 'hdf' => 'application/x-hdf',
'hqx' => 'application/mac-binhex40', 'ico' => 'image/vnd.microsoft.icon', 'ips' => 'application/x-ipscript',
'ipx' => 'application/x-ipix', 'js' => 'application/x-javascript', 'latex' => 'application/x-latex',
'lha' => 'application/octet-stream', 'lsp' => 'application/x-lisp', 'lzh' => 'application/octet-stream',
'man' => 'application/x-troff-man', 'me' => 'application/x-troff-me', 'mif' => 'application/vnd.mif',
'ms' => 'application/x-troff-ms', 'nc' => 'application/x-netcdf', 'oda' => 'application/oda',
'otf' => 'font/otf', 'pdf' => 'application/pdf',
'pgn' => 'application/x-chess-pgn', 'pot' => 'application/mspowerpoint', 'pps' => 'application/mspowerpoint',
'ppt' => 'application/mspowerpoint', 'ppz' => 'application/mspowerpoint', 'pre' => 'application/x-freelance',
'prt' => 'application/pro_eng', 'ps' => 'application/postscript', 'roff' => 'application/x-troff',
'scm' => 'application/x-lotusscreencam', 'set' => 'application/set', 'sh' => 'application/x-sh',
'shar' => 'application/x-shar', 'sit' => 'application/x-stuffit', 'skd' => 'application/x-koan',
'skm' => 'application/x-koan', 'skp' => 'application/x-koan', 'skt' => 'application/x-koan',
'smi' => 'application/smil', 'smil' => 'application/smil', 'sol' => 'application/solids',
'spl' => 'application/x-futuresplash', 'src' => 'application/x-wais-source', 'step' => 'application/STEP',
'stl' => 'application/SLA', 'stp' => 'application/STEP', 'sv4cpio' => 'application/x-sv4cpio',
'sv4crc' => 'application/x-sv4crc', 'svg' => 'image/svg+xml', 'svgz' => 'image/svg+xml',
'swf' => 'application/x-shockwave-flash', 't' => 'application/x-troff',
'tar' => 'application/x-tar', 'tcl' => 'application/x-tcl', 'tex' => 'application/x-tex',
'texi' => 'application/x-texinfo', 'texinfo' => 'application/x-texinfo', 'tr' => 'application/x-troff',
'tsp' => 'application/dsptype', 'ttf' => 'font/ttf',
'unv' => 'application/i-deas', 'ustar' => 'application/x-ustar',
'vcd' => 'application/x-cdlink', 'vda' => 'application/vda', 'xlc' => 'application/vnd.ms-excel',
'xll' => 'application/vnd.ms-excel', 'xlm' => 'application/vnd.ms-excel', 'xls' => 'application/vnd.ms-excel',
'xlw' => 'application/vnd.ms-excel', 'zip' => 'application/zip', 'aif' => 'audio/x-aiff', 'aifc' => 'audio/x-aiff',
'aiff' => 'audio/x-aiff', 'au' => 'audio/basic', 'kar' => 'audio/midi', 'mid' => 'audio/midi',
'midi' => 'audio/midi', 'mp2' => 'audio/mpeg', 'mp3' => 'audio/mpeg', 'mpga' => 'audio/mpeg',
'ra' => 'audio/x-realaudio', 'ram' => 'audio/x-pn-realaudio', 'rm' => 'audio/x-pn-realaudio',
'rpm' => 'audio/x-pn-realaudio-plugin', 'snd' => 'audio/basic', 'tsi' => 'audio/TSP-audio', 'wav' => 'audio/x-wav',
'asc' => 'text/plain', 'c' => 'text/plain', 'cc' => 'text/plain', 'css' => 'text/css', 'etx' => 'text/x-setext',
'f' => 'text/plain', 'f90' => 'text/plain', 'h' => 'text/plain', 'hh' => 'text/plain', 'htm' => 'text/html',
'html' => 'text/html', 'm' => 'text/plain', 'rtf' => 'text/rtf', 'rtx' => 'text/richtext', 'sgm' => 'text/sgml',
'sgml' => 'text/sgml', 'tsv' => 'text/tab-separated-values', 'tpl' => 'text/template', 'txt' => 'text/plain',
'xml' => 'text/xml', 'avi' => 'video/x-msvideo', 'fli' => 'video/x-fli', 'mov' => 'video/quicktime',
'movie' => 'video/x-sgi-movie', 'mpe' => 'video/mpeg', 'mpeg' => 'video/mpeg', 'mpg' => 'video/mpeg',
'qt' => 'video/quicktime', 'viv' => 'video/vnd.vivo', 'vivo' => 'video/vnd.vivo', 'gif' => 'image/gif',
'ief' => 'image/ief', 'jpe' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'jpg' => 'image/jpeg',
'pbm' => 'image/x-portable-bitmap', 'pgm' => 'image/x-portable-graymap', 'png' => 'image/png',
'pnm' => 'image/x-portable-anymap', 'ppm' => 'image/x-portable-pixmap', 'ras' => 'image/cmu-raster',
'rgb' => 'image/x-rgb', 'tif' => 'image/tiff', 'tiff' => 'image/tiff', 'xbm' => 'image/x-xbitmap',
'xpm' => 'image/x-xpixmap', 'xwd' => 'image/x-xwindowdump', 'ice' => 'x-conference/x-cooltalk',
'iges' => 'model/iges', 'igs' => 'model/iges', 'mesh' => 'model/mesh', 'msh' => 'model/mesh',
'silo' => 'model/mesh', 'vrml' => 'model/vrml', 'wrl' => 'model/vrml',
'mime' => 'www/mime', 'pdb' => 'chemical/x-pdb', 'xyz' => 'chemical/x-pdb'
);
/**
* Protocol header to send to the client
*
* @var string
*/
protected $_protocol = 'HTTP/1.1';
/**
* Status code to send to the client
*
* @var integer
*/
protected $_status = 200;
/**
* Content type to send. This can be an 'extension' that will be transformed using the $_mimetypes array
* or a complete mime-type
*
* @var integer
*/
protected $_contetType = 'html';
/**
* Buffer list of headers
*
* @var array
*/
protected $_headers = array();
/**
* Buffer string for response message
*
* @var string
*/
protected $_body = null;
/**
* Encoding string to send
*
* @var string
*/
protected $_encoding = 'UTF-8';
/**
* The object for the current request
*
* @var CakeRequest
*/
protected $_request = null;
/**
* Class constructor
*
* @param array $options list of parameters to setup the response. Possible values are:
* - body: the rensonse text that should be sent to the client
* - status: the HTTP status code to respond with
* - type: a complete mime-type string or an extension mapepd in this class
* - encoding: the encoding for the response body
* @param CakeRequest $request the object representing the current request
* @return void
*/
public function __construct(array $options = array(), CakeRequest $request = null) {
}
/**
* Sends the complete response to the client including headers and message body
*
*/
public function send() {
}
/**
* Sends the complete headers list to the client
*
*/
public function sendHeaders() {
}
/**
* Buffers a header string to be sent
*
* @param mixed $header. An array of header strings or a single header string
*/
public function header($header) {
}
/**
* Buffers the response message to be sent
* if $content is null the current buffer is returned
*
* @param string $content the string message to be sent
* @return string current message buffer if $content param is passed as null
*/
public function body($content = null) {
}
/**
* Sets the HTTP status code to be sent
* if $code is null the current code is returned
*
* @param integer $code
* @return integer current status code if $code param is passed as null
*/
public function statusCode($code = null) {
}
/**
* Sets the correct headers to instruct the client to not cache te response
*
* @return void
*/
public function disableCache() {
}
/**
* Sets the correct headers to instruct the client to cache the response
*
* @param string $since a valid time since the response text has not been modified
* @param string $time a valid time for cache expiry
* @return void
*/
public function cache($since, $time = '+1 day') {
}
/**
* Sets the correct headers and output buffering handler to send a compressed response
*
* @return boolean false if client does not accept compressed responses or no handler is available, true otherwise
*/
public function compress() {
}
}

View file

@ -225,7 +225,7 @@ class CakeSession extends Object {
* @return boolean True if session has been started.
*/
function started() {
if (isset($_SESSION) && session_id()) {
if (!empty($_SESSION) && session_id()) {
return true;
}
return false;
@ -729,7 +729,7 @@ class CakeSession extends Object {
* Helper function called on write for database sessions.
*
* @param integer $id ID that uniquely identifies session in database
* @param mixed $data The value of the the data to be saved.
* @param mixed $data The value of the data to be saved.
* @return boolean True for successful write, false otherwise.
* @access private
*/

View file

@ -249,7 +249,7 @@ class Configure {
trigger_error(sprintf(__('Configure::load() - no variable $config found in %s.php'), $fileName), E_USER_WARNING);
return false;
}
return Configure::write($config);
return self::write($config);
}
/**
@ -263,7 +263,7 @@ class Configure {
public static function version() {
if (!isset(self::$_values['Cake']['version'])) {
require(CORE_PATH . 'cake' . DS . 'config' . DS . 'config.php');
Configure::write($config);
self::write($config);
}
return self::$_values['Cake']['version'];
}
@ -292,7 +292,7 @@ class Configure {
if (is_null($type)) {
$write = false;
}
Configure::__writeConfig($content, $name, $write);
self::__writeConfig($content, $name, $write);
}
/**
@ -308,7 +308,7 @@ class Configure {
private static function __writeConfig($content, $name, $write = true) {
$file = CACHE . 'persistent' . DS . $name . '.php';
if (Configure::read('debug') > 0) {
if (self::read('debug') > 0) {
$expires = "+10 seconds";
} else {
$expires = "+999 days";
@ -320,13 +320,9 @@ class Configure {
}
if ($write === true) {
if (!class_exists('File')) {
require LIBS . 'file.php';
}
$fileClass = new File($file);
if ($fileClass->writable()) {
$fileClass->append($content);
$fileClass = new SplFileObject($file, 'a');
if ($fileClass->isWritable()) {
$fileClass->fwrite($content);
}
}
}

View file

@ -151,7 +151,7 @@ class AuthComponent extends Object {
public $loginRedirect = null;
/**
* The the default action to redirect to after the user is logged out. While AuthComponent does
* The default action to redirect to after the user is logged out. While AuthComponent does
* not handle post-logout redirection, a redirect URL will be returned from AuthComponent::logout().
* Defaults to AuthComponent::$loginAction.
*
@ -303,6 +303,7 @@ class AuthComponent extends Object {
$methods = array_flip($controller->methods);
$action = $controller->request->params['action'];
$isMissingAction = (
$controller->scaffold === false &&
!isset($methods[$action])

View file

@ -719,7 +719,16 @@ class EmailComponent extends Object{
if ($this->delivery == 'mail') {
$nl = '';
}
return mb_encode_mimeheader($subject, $this->charset, 'B', $nl);
$internalEncoding = function_exists('mb_internal_encoding');
if ($internalEncoding) {
$restore = mb_internal_encoding();
mb_internal_encoding($this->charset);
}
$return = mb_encode_mimeheader($subject, $this->charset, 'B', $nl);
if ($internalEncoding) {
mb_internal_encoding($restore);
}
return $return;
}
/**

View file

@ -481,7 +481,7 @@ class Controller extends Object {
}
/**
* Loads Model classes based on the the uses property
* Loads Model classes based on the uses property
* see Controller::loadModel(); for more info.
* Loads Components and prepares them for initialization.
*
@ -849,6 +849,7 @@ class Controller extends Object {
*/
public function render($action = null, $layout = null, $file = null) {
$this->beforeRender();
$this->Component->triggerCallback('beforeRender', $this);
$viewClass = $this->view;
if ($this->view != 'View') {
@ -857,8 +858,6 @@ class Controller extends Object {
App::import('View', $this->view);
}
$this->Component->triggerCallback('beforeRender', $this);
$this->params['models'] = $this->modelNames;
$View = new $viewClass($this);

View file

@ -194,7 +194,10 @@ class HttpSocket extends CakeSocket {
$request['uri'] = null;
}
$uri = $this->_parseUri($request['uri']);
$hadAuth = false;
if (is_array($uri) && array_key_exists('user', $uri)) {
$hadAuth = true;
}
if (!isset($uri['host'])) {
$host = $this->config['host'];
}
@ -202,11 +205,14 @@ class HttpSocket extends CakeSocket {
$host = $request['host'];
unset($request['host']);
}
$request['uri'] = $this->url($request['uri']);
$request['uri'] = $this->_parseUri($request['uri'], true);
$this->request = Set::merge($this->request, $this->config['request'], $request);
if (!$hadAuth && !empty($this->config['request']['auth']['user'])) {
$this->request['uri']['user'] = $this->config['request']['auth']['user'];
$this->request['uri']['pass'] = $this->config['request']['auth']['pass'];
}
$this->_configUri($this->request['uri']);
if (isset($host)) {
@ -219,7 +225,23 @@ class HttpSocket extends CakeSocket {
if (!empty($this->request['cookies'])) {
$cookies = $this->buildCookies($this->request['cookies']);
}
$this->request['header'] = array_merge(array('Host' => $this->request['uri']['host']), $this->request['header']);
$Host = $this->request['uri']['host'];
$schema = '';
$port = 0;
if (isset($this->request['uri']['schema'])) {
$schema = $this->request['uri']['schema'];
}
if (isset($this->request['uri']['port'])) {
$port = $this->request['uri']['port'];
}
if (
($schema === 'http' && $port != 80) ||
($schema === 'https' && $port != 443) ||
($port != 80 && $port != 443)
) {
$Host .= ':' . $port;
}
$this->request['header'] = array_merge(compact('Host'), $this->request['header']);
}
if (isset($this->request['auth']['user']) && isset($this->request['auth']['pass'])) {
@ -594,7 +616,6 @@ class HttpSocket extends CakeSocket {
if (!isset($uri['host'])) {
return false;
}
$config = array(
'request' => array(
'uri' => array_intersect_key($uri, $this->config['request']['uri']),
@ -1030,7 +1051,6 @@ class HttpSocket extends CakeSocket {
if (empty($initalState)) {
$initalState = get_class_vars(__CLASS__);
}
if ($full == false) {
$this->request = $initalState['request'];
$this->response = $initalState['response'];

View file

@ -21,7 +21,7 @@
/**
* Included libraries.
*/
App::import('Core', 'l10n');
App::import('Core', array('l10n', 'Multibyte'));
/**
* I18n handles translation of Text and time format strings.

View file

@ -204,7 +204,7 @@ class TreeBehavior extends ModelBehavior {
* @return integer number of child nodes
* @link http://book.cakephp.org/view/1347/Counting-children
*/
public function childcount(&$Model, $id = null, $direct = false) {
public function childCount(&$Model, $id = null, $direct = false) {
if (is_array($id)) {
extract (array_merge(array('id' => null), $id));
}
@ -307,7 +307,7 @@ class TreeBehavior extends ModelBehavior {
* @return array An associative array of records, where the id is the key, and the display field is the value
* @link http://book.cakephp.org/view/1348/generatetreelist
*/
public function generatetreelist(&$Model, $conditions = null, $keyPath = null, $valuePath = null, $spacer = '_', $recursive = null) {
public function generateTreeList(&$Model, $conditions = null, $keyPath = null, $valuePath = null, $spacer = '_', $recursive = null) {
$overrideRecursive = $recursive;
extract($this->settings[$Model->alias]);
if (!is_null($overrideRecursive)) {
@ -362,7 +362,7 @@ class TreeBehavior extends ModelBehavior {
* @return array Array of data for the parent node
* @link http://book.cakephp.org/view/1349/getparentnode
*/
public function getparentnode(&$Model, $id = null, $fields = null, $recursive = null) {
public function getParentNode(&$Model, $id = null, $fields = null, $recursive = null) {
if (is_array($id)) {
extract (array_merge(array('id' => null), $id));
}
@ -395,7 +395,7 @@ class TreeBehavior extends ModelBehavior {
* @return array Array of nodes from top most parent to current node
* @link http://book.cakephp.org/view/1350/getpath
*/
public function getpath(&$Model, $id = null, $fields = null, $recursive = null) {
public function getPath(&$Model, $id = null, $fields = null, $recursive = null) {
if (is_array($id)) {
extract (array_merge(array('id' => null), $id));
}
@ -432,7 +432,7 @@ class TreeBehavior extends ModelBehavior {
* @return boolean true on success, false on failure
* @link http://book.cakephp.org/view/1352/moveDown
*/
public function movedown(&$Model, $id = null, $number = 1) {
public function moveDown(&$Model, $id = null, $number = 1) {
if (is_array($id)) {
extract (array_merge(array('id' => null), $id));
}
@ -490,7 +490,7 @@ class TreeBehavior extends ModelBehavior {
* @return boolean true on success, false on failure
* @link http://book.cakephp.org/view/1353/moveUp
*/
public function moveup(&$Model, $id = null, $number = 1) {
public function moveUp(&$Model, $id = null, $number = 1) {
if (is_array($id)) {
extract (array_merge(array('id' => null), $id));
}
@ -601,7 +601,7 @@ class TreeBehavior extends ModelBehavior {
} else {
$db =& ConnectionManager::getDataSource($Model->useDbConfig);
foreach ($Model->find('all', array('conditions' => $scope, 'fields' => array($Model->primaryKey, $parent), 'order' => $left)) as $array) {
$path = $this->getpath($Model, $array[$Model->alias][$Model->primaryKey]);
$path = $this->getPath($Model, $array[$Model->alias][$Model->primaryKey]);
if ($path == null || count($path) < 2) {
$parentId = null;
} else {
@ -673,7 +673,7 @@ class TreeBehavior extends ModelBehavior {
* @return boolean true on success, false on failure
* @link http://book.cakephp.org/view/1354/removeFromTree
*/
public function removefromtree(&$Model, $id = null, $delete = false) {
public function removeFromTree(&$Model, $id = null, $delete = false) {
if (is_array($id)) {
extract (array_merge(array('id' => null), $id));
}

View file

@ -818,7 +818,7 @@ class DboSource extends DataSource {
$db =& $this;
}
if (isset($db)) {
if (isset($db) && method_exists($db, 'queryAssociation')) {
$stack = array($assoc);
$db->queryAssociation($model, $linkModel, $type, $assoc, $assocData, $array, true, $resultSet, $model->recursive - 1, $stack);
unset($db);
@ -1191,10 +1191,10 @@ class DboSource extends DataSource {
} elseif (!empty($model->hasMany) && $model->recursive > -1) {
$assocFields = $this->fields($model, $model->alias, array("{$model->alias}.{$model->primaryKey}"));
$passedFields = $this->fields($model, $model->alias, $queryData['fields']);
if (count($passedFields) === 1) {
$match = strpos($passedFields[0], $assocFields[0]);
$match1 = strpos($passedFields[0], 'COUNT(');
$match1 = (bool)preg_match('/^[a-z]+\(/i', $passedFields[0]);
if ($match === false && $match1 === false) {
$queryData['fields'] = array_merge($passedFields, $assocFields);
} else {

View file

@ -383,7 +383,7 @@ class Model extends Object {
*
* ### Dynamically creating models
*
* You can dynamically create model instances using the the $id array syntax.
* You can dynamically create model instances using the $id array syntax.
*
* {{{
* $Post = new Model(array('table' => 'posts', 'name' => 'Post', 'ds' => 'connection2'));
@ -596,10 +596,9 @@ class Model extends Object {
*/
function bindModel($params, $reset = true) {
foreach ($params as $assoc => $model) {
if ($reset === true) {
if ($reset === true && !isset($this->__backAssociation[$assoc])) {
$this->__backAssociation[$assoc] = $this->{$assoc};
}
foreach ($model as $key => $value) {
$assocName = $key;
@ -612,6 +611,9 @@ class Model extends Object {
if (property_exists($this, $assocName)) {
unset($this->{$assocName});
}
if ($reset === false && isset($this->__backAssociation[$assoc])) {
$this->__backAssociation[$assoc][$assocName] = $value;
}
}
}
$this->__createLinks();
@ -639,14 +641,14 @@ class Model extends Object {
*/
function unbindModel($params, $reset = true) {
foreach ($params as $assoc => $models) {
if ($reset === true) {
if ($reset === true && !isset($this->__backAssociation[$assoc])) {
$this->__backAssociation[$assoc] = $this->{$assoc};
}
foreach ($models as $model) {
$this->__backAssociation = array_merge($this->__backAssociation, $this->{$assoc});
unset ($this->__backAssociation[$model]);
unset ($this->{$assoc}[$model]);
if ($reset === false && isset($this->__backAssociation[$assoc][$model])) {
unset($this->__backAssociation[$assoc][$model]);
}
unset($this->{$assoc}[$model]);
}
}
return true;
@ -2355,9 +2357,9 @@ class Model extends Object {
}
/**
* Called only when bindTo<ModelName>() is used.
* This resets the association arrays for the model back
* to those originally defined in the model.
* to those originally defined in the model. Normally called at the end
* of each call to Model::find()
*
* @return boolean Success
*/

4
cake/libs/view/helpers/form.php Executable file → Normal file
View file

@ -258,7 +258,7 @@ class FormHelper extends AppHelper {
0 => $id
);
if (!empty($options['action']) && !isset($options['id'])) {
$options['id'] = $model . Inflector::camelize($options['action']) . 'Form';
$options['id'] = $this->domId($options['action'] . 'Form');
}
$options['action'] = array_merge($actionDefaults, (array)$options['url']);
} elseif (is_string($options['url'])) {
@ -2158,7 +2158,7 @@ class FormHelper extends AppHelper {
*
* Options
*
* - `secure` - boolean whether or not the the field should be added to the security fields.
* - `secure` - boolean whether or not the field should be added to the security fields.
*
* @param string $field Name of the field to initialize options for.
* @param array $options Array of options to append options into.

View file

@ -21,7 +21,7 @@ if (Configure::read() == 0):
endif;
?>
<h2><?php echo sprintf(__('Release Notes for CakePHP %s.', true), Configure::version()); ?></h2>
<a href="http://cakephp.lighthouseapp.com/projects/42648/changelog-1-3-2"><?php __('Read the changelog'); ?> </a>
<a href="http://cakephp.lighthouseapp.com/projects/42648/changelog-1-3-3"><?php __('Read the changelog'); ?> </a>
<?php
if (Configure::read() > 0):
Debugger::checkSecurityKeys();

View file

@ -356,6 +356,7 @@ class SchemaShellTest extends CakeTestCase {
$file = new File(TMP . 'tests' . DS . 'schema.php');
$contents = $file->read();
$this->assertPattern('/class TestPluginSchema/', $contents);
$this->assertPattern('/var \$posts/', $contents);
$this->assertPattern('/var \$auth_users/', $contents);
$this->assertPattern('/var \$authors/', $contents);

View file

@ -309,6 +309,28 @@ class CacheTest extends CakeTestCase {
$this->assertIdentical(Cache::read('App.zeroTest2'), '0');
}
/**
* Test that failed writes cause errors to be triggered.
*
* @return void
*/
function testWriteTriggerError() {
App::build(array(
'libs' => array(TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'libs' . DS),
'plugins' => array(TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'plugins' . DS)
), true);
Cache::config('test_trigger', array('engine' => 'TestAppCache'));
try {
Cache::write('fail', 'value', 'test_trigger');
$this->fail('No exception thrown');
} catch (PHPUnit_Framework_Error $e) {
$this->assertTrue(true);
}
Cache::drop('test_trigger');
App::build();
}
/**
* testCacheDisable method
*

View file

@ -260,6 +260,10 @@ class CakeSessionTest extends CakeTestCase {
$this->Session->destroy();
$this->assertFalse($this->Session->check('bulletProof'));
$this->assertNotEqual($id, $this->Session->id());
$this->Session->cookieLifeTime = 'test';
$this->Session->destroy();
$this->assertNotEqual('test', $this->Session->cookieLifeTime);
}
/**

View file

@ -864,7 +864,38 @@ HTMLBLOC;
$result = $this->Controller->EmailTest->strip($content, true);
$expected = $content;
$this->assertEqual($result, $expected);
}
/**
* test that the _encode() will set mb_internal_encoding.
*
* @return void
*/
function test_encodeSettingInternalCharset() {
$skip = !function_exists('mb_internal_encoding');
if ($this->skipIf($skip, 'Missing mb_* functions, cannot run test.')) {
return;
}
mb_internal_encoding('ISO-8859-1');
$this->Controller->charset = 'UTF-8';
$this->Controller->EmailTest->to = 'postmaster@localhost';
$this->Controller->EmailTest->from = 'noreply@example.com';
$this->Controller->EmailTest->subject = 'هذه رسالة بعنوان طويل مرسل للمستلم';
$this->Controller->EmailTest->replyTo = 'noreply@example.com';
$this->Controller->EmailTest->template = null;
$this->Controller->EmailTest->delivery = 'debug';
$this->Controller->EmailTest->sendAs = 'text';
$this->assertTrue($this->Controller->EmailTest->send('This is the body of the message'));
$subject = '=?UTF-8?B?2YfYsNmHINix2LPYp9mE2Kkg2KjYudmG2YjYp9mGINi32YjZitmEINmF2LE=?=' . "\r\n" . ' =?UTF-8?B?2LPZhCDZhNmE2YXYs9iq2YTZhQ==?=';
preg_match('/Subject: (.*)Header:/s', $this->Controller->Session->read('Message.email.message'), $matches);
$this->assertEqual(trim($matches[1]), $subject);
$result = mb_internal_encoding();
$this->assertEqual($result, 'ISO-8859-1');
}
/**
@ -874,6 +905,7 @@ HTMLBLOC;
* @return void
*/
function testMultibyte() {
$this->Controller->charset = 'UTF-8';
$this->Controller->EmailTest->to = 'postmaster@localhost';
$this->Controller->EmailTest->from = 'noreply@example.com';
$this->Controller->EmailTest->subject = 'هذه رسالة بعنوان طويل مرسل للمستلم';

View file

@ -347,38 +347,37 @@ class SessionComponentTest extends CakeTestCase {
* @return void
*/
function testSessionTimeout() {
Configure::write('debug', 2);
Configure::write('Security.level', 'low');
session_destroy();
Configure::write('Security.level', 'low');
$Session = new SessionComponent();
$Session =& new SessionComponent();
$Session->destroy();
$Session->write('Test', 'some value');
$this->assertEqual($Session->sessionTime, mktime() + (300 * Configure::read('Session.timeout')));
$this->assertEqual($Session->sessionTime, time() + (300 * Configure::read('Session.timeout')));
$this->assertEqual($_SESSION['Config']['timeout'], 10);
$this->assertEqual($_SESSION['Config']['time'], $Session->sessionTime);
$this->assertEqual($Session->time, mktime());
$this->assertEqual($_SESSION['Config']['time'], $Session->time + (Security::inactiveMins() * Configure::read('Session.timeout')));
$this->assertEqual($Session->time, time());
$this->assertEqual($_SESSION['Config']['time'], $Session->time + (300 * Configure::read('Session.timeout')));
session_destroy();
Configure::write('Security.level', 'medium');
$Session = new SessionComponent();
$Session =& new SessionComponent();
$Session->destroy();
$Session->write('Test', 'some value');
$this->assertEqual($Session->sessionTime, mktime() + (100 * Configure::read('Session.timeout')));
$this->assertEqual($_SESSION['Config']['timeout'], 10);
$this->assertEqual($_SESSION['Config']['time'], $Session->sessionTime);
$this->assertEqual($Session->time, mktime());
$this->assertEqual($Session->time, time());
$this->assertEqual($_SESSION['Config']['time'], $Session->time + (Security::inactiveMins() * Configure::read('Session.timeout')));
session_destroy();
Configure::write('Security.level', 'high');
$Session = new SessionComponent();
$Session =& new SessionComponent();
$Session->destroy();
$Session->write('Test', 'some value');
$this->assertEqual($Session->sessionTime, mktime() + (10 * Configure::read('Session.timeout')));
$this->assertEqual($Session->sessionTime, time() + (10 * Configure::read('Session.timeout')));
$this->assertEqual($_SESSION['Config']['timeout'], 10);
$this->assertEqual($_SESSION['Config']['time'], $Session->sessionTime);
$this->assertEqual($Session->time, mktime());
$this->assertEqual($Session->time, time());
$this->assertEqual($_SESSION['Config']['time'], $Session->time + (Security::inactiveMins() * Configure::read('Session.timeout')));
}
}

View file

@ -391,6 +391,16 @@ class TestComponent extends Object {
*/
function shutdown(&$controller) {
}
/**
* beforeRender callback
*
* @return void
*/
function beforeRender(&$controller) {
if ($this->viewclass) {
$controller->view = $this->viewclass;
}
}
}
/**
@ -954,6 +964,31 @@ class ControllerTest extends CakeTestCase {
App::build();
}
/**
* test that a component beforeRender can change the controller view class.
*
* @return void
*/
function testComponentBeforeRenderChangingViewClass() {
$core = App::core('views');
App::build(array(
'views' => array(
TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'views'. DS,
$core[0]
)
), true);
$Controller =& new Controller();
$Controller->uses = array();
$Controller->components = array('Test');
$Controller->constructClasses();
$Controller->Test->viewclass = 'Theme';
$Controller->viewPath = 'posts';
$Controller->theme = 'test_theme';
$result = $Controller->render('index');
$this->assertPattern('/default test_theme layout/', $result);
App::build();
}
/**
* testToBeInheritedGuardmethods method
*

View file

@ -454,6 +454,25 @@ class HttpSocketTest extends CakeTestCase {
)
)
, 9 => array(
'request' => array('method' => 'POST', 'uri' => 'http://www.cakephp.org:8080/posts/add', 'body' => array('name' => 'HttpSocket-is-released', 'date' => 'today'))
, 'expectation' => array(
'config' => array(
'port' => 8080
, 'request' => array(
'uri' => array(
'port' => 8080
)
)
)
, 'request' => array(
'uri' => array(
'port' => 8080
)
, 'header' => "Host: www.cakephp.org:8080\r\nConnection: close\r\nUser-Agent: CakePHP\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 38\r\n"
)
)
)
, 10 => array(
'request' => array('method' => 'POST', 'uri' => 'https://www.cakephp.org/posts/add', 'body' => array('name' => 'HttpSocket-is-released', 'date' => 'today'))
, 'expectation' => array(
'config' => array(
@ -470,10 +489,11 @@ class HttpSocketTest extends CakeTestCase {
'scheme' => 'https'
, 'port' => 443
)
, 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 38\r\n"
)
)
)
, 10 => array(
, 11 => array(
'request' => array(
'method' => 'POST',
'uri' => 'https://www.cakephp.org/posts/add',
@ -659,6 +679,31 @@ class HttpSocketTest extends CakeTestCase {
$this->RequestSocket->get('http://www.google.com/', null, array('auth' => array('user' => 'foo', 'pass' => 'bar')));
}
/**
* test that two consecutive get() calls reset the authentication credentials.
*
* @return void
*/
function testConsecutiveGetResetsAuthCredentials() {
$socket = new MockHttpSocket();
$socket->config['request']['auth'] = array(
'method' => 'Basic',
'user' => 'mark',
'pass' => 'secret'
);
$socket->get('http://mark:secret@example.com/test');
$this->assertEqual($socket->request['uri']['user'], 'mark');
$this->assertEqual($socket->request['uri']['pass'], 'secret');
$socket->get('/test2');
$this->assertEqual($socket->request['auth']['user'], 'mark');
$this->assertEqual($socket->request['auth']['pass'], 'secret');
$socket->get('/test3');
$this->assertEqual($socket->request['auth']['user'], 'mark');
$this->assertEqual($socket->request['auth']['pass'], 'secret');
}
/**
* testPostPutDelete method
*

View file

@ -858,7 +858,7 @@ class NumberTreeTest extends CakeTestCase {
$result = $this->Tree->verify();
$this->assertIdentical($result, true);
$this->Tree->moveup();
$this->Tree->moveUp();
$result = $this->Tree->find('all', array('fields' => 'name', 'order' => $modelClass . '.' . $leftField . ' ASC'));
$expected = array(array($modelClass => array('name' => '1.1')),
@ -1132,7 +1132,7 @@ class NumberTreeTest extends CakeTestCase {
$data = $this->Tree->find(array($modelClass . '.name' => '1.2.2'));
$this->Tree->id= $data[$modelClass]['id'];
$result = $this->Tree->getparentNode(null, array('name'));
$result = $this->Tree->getParentNode(null, array('name'));
$expects = array($modelClass => array('name' => '1.2'));
$this->assertIdentical($result, $expects);
}

View file

@ -1339,6 +1339,7 @@ class DboSourceTest extends CakeTestCase {
function endTest() {
unset($this->Model);
Configure::write('debug', $this->debug);
ClassRegistry::flush();
unset($this->debug);
}
@ -2043,6 +2044,28 @@ class DboSourceTest extends CakeTestCase {
unset($this->Model->hasMany['TestModel6']['fields']);
}
/**
* test generateAssociationQuery with a hasMany and an aggregate function.
*
* @return void
*/
function testGenerateAssociationQueryHasManyAndAggregateFunction() {
$this->Model =& new TestModel5();
$this->Model->schema();
$this->_buildRelatedModels($this->Model);
$binding = array('type' => 'hasMany', 'model' => 'TestModel6');
$queryData = array('fields' => array('MIN(TestModel5.test_model4_id)'));
$resultSet = null;
$null = null;
$params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding);
$this->Model->recursive = 0;
$result = $this->testDb->generateAssociationQuery($this->Model, $null, $params['type'], $params['assoc'], $params['assocData'], $queryData, false, $resultSet);
$this->assertPattern('/^SELECT\s+MIN\(`TestModel5`\.`test_model4_id`\)\s+FROM/', $result);
}
/**
* testGenerateAssociationQueryHasAndBelongsToMany method
*
@ -4440,4 +4463,19 @@ class DboSourceTest extends CakeTestCase {
$result = $this->testDb->fullTableName($Article, false);
$this->assertEqual($result, 'tbl_articles');
}
/**
* test that read() only calls queryAssociation on db objects when the method is defined.
*
* @return void
*/
function testReadOnlyCallingQueryAssociationWhenDefined() {
ConnectionManager::create('test_no_queryAssociation', array(
'datasource' => 'data'
));
$Article =& ClassRegistry::init('Article');
$Article->Comment->useDbConfig = 'test_no_queryAssociation';
$result = $Article->find('all');
$this->assertTrue(is_array($result));
}
}

View file

@ -4737,6 +4737,57 @@ class ModelReadTest extends BaseModelTest {
$this->assertEqual($result, $expected);
}
/**
* test that multiple reset = true calls to bindModel() result in the original associations.
*
* @return void
*/
function testBindModelMultipleTimesResetCorrectly() {
$this->loadFixtures('User', 'Comment', 'Article');
$TestModel =& new User();
$TestModel->bindModel(array('hasMany' => array('Comment')));
$TestModel->bindModel(array('hasMany' => array('Comment')));
$TestModel->resetAssociations();
$this->assertFalse(isset($TestModel->hasMany['Comment']), 'Association left behind');
}
/**
* testBindMultipleTimes method with different reset settings
*
* @access public
* @return void
*/
function testBindMultipleTimesWithDifferentResetSettings() {
$this->loadFixtures('User', 'Comment', 'Article');
$TestModel =& new User();
$result = $TestModel->hasMany;
$expected = array();
$this->assertEqual($result, $expected);
$result = $TestModel->bindModel(array(
'hasMany' => array('Comment')
));
$this->assertTrue($result);
$result = $TestModel->bindModel(
array('hasMany' => array('Article')),
false
);
$this->assertTrue($result);
$result = array_keys($TestModel->hasMany);
$expected = array('Comment', 'Article');
$this->assertEqual($result, $expected);
$TestModel->resetAssociations();
$result = array_keys($TestModel->hasMany);
$expected = array('Article');
$this->assertEqual($result, $expected);
}
/**
* test that bindModel behaves with Custom primary Key associations
*
@ -4756,6 +4807,58 @@ class ModelReadTest extends BaseModelTest {
$this->assertFalse(empty($result));
}
/**
* test that calling unbindModel() with reset == true multiple times
* leaves associations in the correct state.
*
* @return void
*/
function testUnbindMultipleTimesResetCorrectly() {
$this->loadFixtures('User', 'Comment', 'Article');
$TestModel =& new Article10();
$TestModel->unbindModel(array('hasMany' => array('Comment')));
$TestModel->unbindModel(array('hasMany' => array('Comment')));
$TestModel->resetAssociations();
$this->assertTrue(isset($TestModel->hasMany['Comment']), 'Association permanently removed');
}
/**
* testBindMultipleTimes method with different reset settings
*
* @access public
* @return void
*/
function testUnBindMultipleTimesWithDifferentResetSettings() {
$this->loadFixtures('User', 'Comment', 'Article');
$TestModel =& new Comment();
$result = array_keys($TestModel->belongsTo);
$expected = array('Article', 'User');
$this->assertEqual($result, $expected);
$result = $TestModel->unbindModel(array(
'belongsTo' => array('User')
));
$this->assertTrue($result);
$result = $TestModel->unbindModel(
array('belongsTo' => array('Article')),
false
);
$this->assertTrue($result);
$result = array_keys($TestModel->belongsTo);
$expected = array();
$this->assertEqual($result, $expected);
$TestModel->resetAssociations();
$result = array_keys($TestModel->belongsTo);
$expected = array('User');
$this->assertEqual($result, $expected);
}
/**
* testAssociationAfterFind method
*
@ -6422,6 +6525,18 @@ class ModelReadTest extends BaseModelTest {
4 => 'garrett (CakePHP)'
);
$this->assertEqual($result, $expected);
$TestModel =& new Article();
$TestModel->displayField = 'title';
$result = $TestModel->find('list', array(
'conditions' => array('User.user' => 'mariano'),
'recursive' => 0
));
$expected = array(
1 => 'First Article',
3 => 'Third Article'
);
$this->assertEqual($result, $expected);
}
/**

View file

@ -1558,7 +1558,7 @@ class ModelWriteTest extends BaseModelTest {
}
/**
* test that saving habtm records respects conditions set in the the 'conditions' key
* test that saving habtm records respects conditions set in the 'conditions' key
* for the association.
*
* @return void

View file

@ -181,6 +181,29 @@ class SanitizeTest extends CakeTestCase {
$expected = '';
$result = Sanitize::clean($string);
$this->assertEqual($string, $expected);
$data = array(
'Grant' => array(
'title' => '2 o clock grant',
'grant_peer_review_id' => 3,
'institution_id' => 5,
'created_by' => 1,
'modified_by' => 1,
'created' => '2010-07-15 14:11:00',
'modified' => '2010-07-19 10:45:41'
),
'GrantsMember' => array(
0 => array(
'id' => 68,
'grant_id' => 120,
'member_id' => 16,
'program_id' => 29,
'pi_percent_commitment' => 1
)
)
);
$result = Sanitize::clean($data);
$this->assertEqual($result, $data);
}
/**

View file

@ -19,7 +19,11 @@
*/
class TestAppCacheEngine extends CacheEngine {
public function write($key, $value, $duration) { }
public function write($key, $value, $duration) {
if ($key = 'fail') {
return false;
}
}
public function read($key) { }