Merge remote branch 'origin/2.0' into 2.0-request

Conflicts:
	cake/libs/controller/components/auth.php
	cake/tests/cases/libs/controller/components/auth.test.php
This commit is contained in:
José Lorenzo Rodríguez Urdaneta 2010-07-27 22:02:08 -04:30
commit 4c71dd845e
56 changed files with 1672 additions and 440 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

@ -155,9 +155,15 @@ class ShellDispatcher {
if (!defined('CAKE_CORE_INCLUDE_PATH')) {
define('DS', DIRECTORY_SEPARATOR);
define('CAKE_CORE_INCLUDE_PATH', dirname(dirname(dirname(__FILE__))));
define('CORE_PATH', CAKE_CORE_INCLUDE_PATH . DS);
define('DISABLE_DEFAULT_ERROR_HANDLING', false);
define('CAKEPHP_SHELL', true);
if (!defined('CORE_PATH')) {
if (function_exists('ini_set') && ini_set('include_path', CAKE_CORE_INCLUDE_PATH . PATH_SEPARATOR . ini_get('include_path'))) {
define('CORE_PATH', null);
} else {
define('CORE_PATH', CAKE_CORE_INCLUDE_PATH . DS);
}
}
}
require_once(CORE_PATH . 'cake' . DS . 'basics.php');
}

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

@ -42,10 +42,10 @@ class TestSuiteShell extends Shell {
} else {
define('TEST_CAKE_CORE_INCLUDE_PATH', CAKE_CORE_INCLUDE_PATH);
}
$params = $this->parseArgs();
$this->_dispatcher = new CakeTestSuiteDispatcher();
$this->_dispatcher->setParams($params);
$this->_dispatcher->loadTestFramework();
require_once CAKE . 'tests' . DS . 'lib' . DS . 'test_manager.php';
}
/**
@ -53,7 +53,7 @@ class TestSuiteShell extends Shell {
*
* @return array Array of params for CakeTestDispatcher
*/
public function parseArgs() {
protected function parseArgs() {
if (empty($this->args)) {
return;
}
@ -61,9 +61,6 @@ class TestSuiteShell extends Shell {
'app' => false,
'plugin' => null,
'output' => 'text',
'codeCoverage' => false,
'filter' => false,
'case' => null
);
$category = $this->args[0];
@ -75,20 +72,32 @@ class TestSuiteShell extends Shell {
}
if (isset($this->args[1])) {
$params['case'] = Inflector::underscore($this->args[1]) . '.test.php';
}
if (isset($this->args[2]) && $this->args[2] == 'cov') {
$params['codeCoverage'] = true;
$params['case'] = Inflector::underscore($this->args[1]);
}
if (isset($this->params['filter'])) {
$params['filter'] = $this->params['filter'];
}
if (isset($this->params['coverage'])) {
$params['codeCoverage'] = true;
$this->params['-filter'] = $this->params['filter'];
}
return $params;
}
/**
* Converts the options passed to the shell as options for the PHPUnit cli runner
*
* @return array Array of params for CakeTestDispatcher
*/
protected function runnerOptions() {
$options = array();
foreach ($this->params as $param => $value) {
if ($param[0] === '-') {
$options[] = '-' . $param;
if (is_string($value)) {
$options[] = $value;
}
}
}
return $options;
}
/**
* Main entry point to this shell
*
@ -98,16 +107,86 @@ class TestSuiteShell extends Shell {
$this->out(__('CakePHP Test Shell'));
$this->hr();
if (count($this->args) == 0) {
$this->error(__('Sorry, you did not pass any arguments!'));
$args = $this->parseArgs();
if (empty($args['case'])) {
$this->available();
}
$result = $this->_dispatcher->dispatch();
$exit = 0;
if ($result instanceof PHPUnit_Framework_TestResult) {
$exit = ($result->errorCount() + $result->failureCount()) > 0;
$this->run($args, $this->runnerOptions());
}
/**
* Runs the test case from $runnerArgs
*
* @param array $runnerArgs list of arguments as obtained from parseArgs()
* @param array $options list of options as constructed by runnerOptions()
* @return void
*/
protected function run($runnerArgs, $options = array()) {
require_once CAKE . 'tests' . DS . 'lib' . DS . 'test_runner.php';
$testCli = new TestRunner($runnerArgs);
$testCli->run($options);
}
/**
* Shows a list of available test cases and gives the option to run one of them
*
* @return void
*/
public function available() {
$params = $this->parseArgs();
$testCases = TestManager::getTestCaseList($params);
$app = $params['app'];
$plugin = $params['plugin'];
$title = "Core Test Cases:";
$category = 'core';
if ($app) {
$title = "App Test Cases:";
$category = 'app';
} elseif ($plugin) {
$title = Inflector::humanize($plugin) . " Test Cases:";
$category = $plugin;
}
if (empty($testCases)) {
$this->out(__("No test cases available \n\n"));
$this->help();
$this->_stop();
}
$this->out($title);
$i = 1;
$cases = array();
foreach ($testCases as $testCaseFile => $testCase) {
$case = explode(DS, str_replace('.test.php', '', $testCase));
$case[count($case) - 1] = Inflector::camelize($case[count($case) - 1]);
$case = implode('/', $case);
$this->out("[$i] $case");
$cases[$i] = $case;
$i++;
}
while ($choice = $this->in(__('What test case would you like to run?'), null, 'q')) {
if (is_numeric($choice) && isset($cases[$choice])) {
$this->args[0] = $category;
$this->args[1] = $cases[$choice];
$this->run($this->parseArgs(), $this->runnerOptions());
break;
}
if (is_string($choice) && in_array($choice, $cases)) {
$this->args[0] = $category;
$this->args[1] = $choice;
$this->run($this->parseArgs(), $this->runnerOptions());
break;
}
if ($choice == 'q') {
break;
}
}
$this->_stop($exit);
}
/**
@ -116,36 +195,76 @@ class TestSuiteShell extends Shell {
* @return void
*/
public function help() {
$help = <<<TEXT
Usage:
-----
cake testsuite <category> <file> [params]
- category - "app", "core" or name of a plugin
- file - file name with folder prefix and without the test.php suffix.
$this->out('CakePHP Testsuite:');
$this->hr();
Params:
-------
-filter
The -filter option allows you supply a pattern that is used to match
test method names. This can be a regular expression.
$this->out('The CakPHP Testsuite allows you to run test cases from the command line');
$this->out('If run with no command line arguments, a list of available core test cases will be shown');
$this->hr();
-coverage
Enable code coverage for this run.
$this->out("Usage: cake testuite <category> <file> [params]");
$this->out("\t- category: app, core or name of a plugin");
$this->out("\t- file: file name with folder prefix and without the test.php suffix");
$this->hr();
Examples:
---------
cake testsuite app behaviors/debuggable;
cake testsuite app models/my_model;
cake testsuite app controllers/my_controller
$this->out("Usage: cake testuite available <category> [params]");
$this->out("\t Shows a list of available testcases for the specified category");
$this->out("\t Params list will be used for running the selected test case");
$this->hr();
cake testsuite core libs/file
cake testsuite core libs/router
cake testsuite core libs/set
$this->out('Examples:');
$this->out('cake testsuite app models/my_model');
$this->out("cake testsuite app controllers/my_controller \n");
$this->out('cake testsuite core libs/file');
$this->out("cake testsuite core libs/set \n");
$this->out('cake testsuite bugs models/bug -- for the plugin bugs and its test case models/bug');
$this->hr();
cake testsuite bugs models/bug
// for the plugin 'bugs' and its test case 'models/bug'
$this->out('Params:');
$this->out("--log-junit <file> Log test execution in JUnit XML format to file.");
$this->out("--log-json <file> Log test execution in JSON format.");
TEXT;
$this->out($help);
$this->out("--coverage-html <dir> Generate code coverage report in HTML format.");
$this->out("--coverage-clover <file> Write code coverage data in Clover XML format.");
$this->out("--coverage-source <dir> Write code coverage / source data in XML format.");
$this->out("--story-html <file> Write Story/BDD results in HTML format to file.");
$this->out("--story-text <file> Write Story/BDD results in Text format to file.");
$this->out("--testdox-html <file> Write agile documentation in HTML format to file.");
$this->out("--testdox-text <file> Write agile documentation in Text format to file.");
$this->out("--filter <pattern> Filter which tests to run.");
$this->out("--group ... Only runs tests from the specified group(s).");
$this->out("--exclude-group ... Exclude tests from the specified group(s).");
$this->out("--filter <pattern> Filter which tests to run.");
$this->out("--loader <loader> TestSuiteLoader implementation to use.");
$this->out("--repeat <times> Runs the test(s) repeatedly.");
$this->out("--story Report test execution progress in Story/BDD format.");
$this->out("--tap Report test execution progress in TAP format.");
$this->out("--testdox Report test execution progress in TestDox format.");
$this->out("--colors Use colors in output.");
$this->out("--stderr Write to STDERR instead of STDOUT.");
$this->out("--stop-on-failure Stop execution upon first error or failure.");
$this->out("--verbose Output more verbose information.");
$this->out("--wait Waits for a keystroke after each test.");
$this->out("--skeleton-class Generate Unit class for UnitTest in UnitTest.php.");
$this->out("--skeleton-test Generate UnitTest class for Unit in Unit.php.");
$this->out("--process-isolation Run each test in a separate PHP process.");
$this->out("--no-globals-backup Do not backup and restore \$GLOBALS for each test.");
$this->out("--static-backup Backup and restore static attributes for each test.");
$this->out("--syntax-check Try to check source files for syntax errors.");
$this->out("--bootstrap <file> A \"bootstrap\" PHP file that is run before the tests.");
$this->out("--configuration <file> Read configuration from XML file.");
$this->out("--no-configuration Ignore default configuration file (phpunit.xml).");
$this->out("--include-path <path(s)> Prepend PHP's include_path with given path(s).");
$this->out("-d key[=value] Sets a php.ini value. \n");
}
}

View file

@ -328,7 +328,7 @@ class Dispatcher {
);
if (($isCss && empty($filters['css'])) || ($isJs && empty($filters['js']))) {
header('HTTP/1.1 404 Not Found');
$this->header('HTTP/1.1 404 Not Found');
return $this->_stop();
} elseif ($isCss) {
include WWW_ROOT . DS . $filters['css'];
@ -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');
}
@ -394,21 +395,34 @@ class Dispatcher {
}
}
header("Date: " . date("D, j M Y G:i:s ", filemtime($assetFile)) . 'GMT');
header('Content-type: ' . $contentType);
header("Expires: " . gmdate("D, j M Y H:i:s", time() + DAY) . " GMT");
header("Cache-Control: cache");
header("Pragma: cache");
$this->header("Date: " . date("D, j M Y G:i:s ", filemtime($assetFile)) . 'GMT');
$this->header('Content-type: ' . $contentType);
$this->header("Expires: " . gmdate("D, j M Y H:i:s", time() + DAY) . " GMT");
$this->header("Cache-Control: cache");
$this->header("Pragma: cache");
if ($ext === 'css' || $ext === 'js') {
include($assetFile);
} else {
if ($compressionEnabled) {
ob_clean();
}
readfile($assetFile);
}
if (Configure::read('Asset.compress')) {
if ($compressionEnabled) {
ob_end_flush();
}
}
/**
* Sends the specified headers to the client
*
* @param string $header header to send
* @todo Refactor this to use a response object or similar
* @return void
*/
public function header($header) {
header($header);
}
}

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;
}

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.
*
@ -620,13 +620,7 @@ class Controller extends Object {
}
$cached = false;
$object = null;
$plugin = null;
if ($this->uses === false) {
if ($this->plugin) {
$plugin = $this->plugin . '.';
}
}
list($plugin, $modelClass) = pluginSplit($modelClass, true, $plugin);
list($plugin, $modelClass) = pluginSplit($modelClass, true);
if ($this->persistModel === true) {
$cached = $this->_persist($modelClass, null, $object);
@ -855,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') {
@ -863,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'));
@ -462,16 +462,16 @@ class Model extends Object {
$this->Behaviors = new BehaviorCollection();
if ($this->useTable !== false) {
$this->setDataSource($ds);
if ($this->useTable === null) {
$this->useTable = Inflector::tableize($this->name);
}
$this->setSource($this->useTable);
if ($this->displayField == null) {
$this->displayField = $this->hasField(array('title', 'name', $this->primaryKey));
unset($this->displayField);
}
$this->table = $this->useTable;
$this->tableToModel[$this->table] = $this->alias;
} elseif ($this->table === false) {
$this->table = Inflector::tableize($this->name);
}
@ -492,11 +492,88 @@ class Model extends Object {
if ($result !== array('unhandled')) {
return $result;
}
$db =& ConnectionManager::getDataSource($this->useDbConfig);
$return = $db->query($method, $params, $this);
$return = $this->getDataSource()->query($method, $params, $this);
return $return;
}
/**
* Handles the lazy loading of model associations by lookin in the association arrays for the requested variable
*
* @param string $name variable tested for existance in class
* @return boolean true if the variable exists (if is a not loaded model association it will be created), false otherwise
*/
public function __isset($name) {
$className = false;
foreach ($this->__associations as $type) {
if (isset($name, $this->{$type}[$name])) {
$className = empty($this->{$type}[$name]['className']) ? $name : $this->{$type}[$name]['className'];
break;
} else if ($type == 'hasAndBelongsToMany') {
foreach ($this->{$type} as $k => $relation) {
if (empty($relation['with'])) {
continue;
}
if (is_array($relation['with'])) {
if (key($relation['with']) === $name) {
$className = $name;
}
} else {
list($plugin, $class) = pluginSplit($relation['with']);
if ($class === $name) {
$className = $relation['with'];
}
}
if ($className) {
$assocKey = $k;
$dynamic = !empty($relation['dynamicWith']);
break(2);
}
}
}
}
if (!$className) {
return false;
}
list($plugin, $className) = pluginSplit($className);
if (!ClassRegistry::isKeySet($className) && !empty($dynamic)) {
$this->{$className} = new AppModel(array(
'name' => $className,
'table' => $this->hasAndBelongsToMany[$assocKey]['joinTable'],
'ds' => $this->useDbConfig
));
} else {
$this->__constructLinkedModel($name, $className, $plugin);
}
if (!empty($assocKey)) {
$this->hasAndBelongsToMany[$assocKey]['joinTable'] = $this->{$name}->table;
if (count($this->{$name}->schema()) <= 2 && $this->{$name}->primaryKey !== false) {
$this->{$name}->primaryKey = $this->hasAndBelongsToMany[$assocKey]['foreignKey'];
}
}
return true;
}
/**
* Returns the value of the requested variable if it can be set by __isset()
*
* @param string $name variable requested for it's value or reference
* @return mixed value of requested variable if it is set
*/
function __get($name) {
if ($name === 'displayField') {
return $this->displayField = $this->hasField(array('title', 'name', $this->primaryKey));
}
if (isset($this->{$name})) {
return $this->{$name};
}
}
/**
* Bind model associations on the fly.
*
@ -519,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;
@ -532,6 +608,12 @@ class Model extends Object {
}
$modelName = $assocName;
$this->{$assoc}[$assocName] = $value;
if (property_exists($this, $assocName)) {
unset($this->{$assocName});
}
if ($reset === false && isset($this->__backAssociation[$assoc])) {
$this->__backAssociation[$assoc][$assocName] = $value;
}
}
}
$this->__createLinks();
@ -559,13 +641,13 @@ 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]);
if ($reset === false && isset($this->__backAssociation[$assoc][$model])) {
unset($this->__backAssociation[$assoc][$model]);
}
unset($this->{$assoc}[$model]);
}
}
@ -601,21 +683,12 @@ class Model extends Object {
$this->{$type}[$assoc] = $value;
if (strpos($assoc, '.') !== false) {
$value = $this->{$type}[$assoc];
unset($this->{$type}[$assoc]);
list($plugin, $assoc) = pluginSplit($assoc, true);
$this->{$type}[$assoc] = $value;
list($plugin, $assoc) = pluginSplit($assoc);
$this->{$type}[$assoc] = array('className' => $plugin. '.' . $assoc);
}
}
$className = $assoc;
if (!empty($value['className'])) {
list($plugin, $className) = pluginSplit($value['className'], true);
$this->{$type}[$assoc]['className'] = $className;
$this->__generateAssociation($type, $assoc);
}
$this->__constructLinkedModel($assoc, $plugin . $className);
}
$this->__generateAssociation($type);
}
}
}
@ -625,7 +698,7 @@ class Model extends Object {
*
* @param string $assoc Association name
* @param string $className Class name
* @deprecated $this->$className use $this->$assoc instead. $assoc is the 'key' in the associations array;
* @param string $plugin name of the plugin where $className is located
* examples: public $hasMany = array('Assoc' => array('className' => 'ModelName'));
* usage: $this->Assoc->modelMethods();
*
@ -634,16 +707,16 @@ class Model extends Object {
* @return void
* @access private
*/
function __constructLinkedModel($assoc, $className = null) {
function __constructLinkedModel($assoc, $className = null, $plugin = null) {
if (empty($className)) {
$className = $assoc;
}
if (!isset($this->{$assoc}) || $this->{$assoc}->name !== $className) {
$model = array('class' => $className, 'alias' => $assoc);
$model = array('class' => $plugin . '.' . $className, 'alias' => $assoc);
$this->{$assoc} = ClassRegistry::init($model);
if (strpos($className, '.') !== false) {
ClassRegistry::addObject($className, $this->{$assoc});
if ($plugin) {
ClassRegistry::addObject($plugin . '.' . $className, $this->{$assoc});
}
if ($assoc) {
$this->tableToModel[$this->{$assoc}->table] = $assoc;
@ -655,11 +728,11 @@ class Model extends Object {
* Build an array-based association from string.
*
* @param string $type 'belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany'
* @param string $assocKey
* @return void
* @access private
*/
function __generateAssociation($type) {
foreach ($this->{$type} as $assocKey => $assocData) {
function __generateAssociation($type, $assocKey) {
$class = $assocKey;
$dynamicWith = false;
@ -702,36 +775,11 @@ class Model extends Object {
}
$this->{$type}[$assocKey][$key] = $data;
}
if ($dynamicWith) {
$this->{$type}[$assocKey]['dynamicWith'] = true;
}
if (!empty($this->{$type}[$assocKey]['with'])) {
$joinClass = $this->{$type}[$assocKey]['with'];
if (is_array($joinClass)) {
$joinClass = key($joinClass);
}
$plugin = null;
if (strpos($joinClass, '.') !== false) {
list($plugin, $joinClass) = explode('.', $joinClass);
$plugin .= '.';
$this->{$type}[$assocKey]['with'] = $joinClass;
}
if (!ClassRegistry::isKeySet($joinClass) && $dynamicWith === true) {
$this->{$joinClass} = new AppModel(array(
'name' => $joinClass,
'table' => $this->{$type}[$assocKey]['joinTable'],
'ds' => $this->useDbConfig
));
} else {
$this->__constructLinkedModel($joinClass, $plugin . $joinClass);
$this->{$type}[$assocKey]['joinTable'] = $this->{$joinClass}->table;
}
if (count($this->{$joinClass}->schema()) <= 2 && $this->{$joinClass}->primaryKey !== false) {
$this->{$joinClass}->primaryKey = $this->{$type}[$assocKey]['foreignKey'];
}
}
}
}
@ -739,26 +787,23 @@ class Model extends Object {
* Sets a custom table for your controller class. Used by your controller to select a database table.
*
* @param string $tableName Name of the custom table
* @throws MissingTableException when database table $tableName is not found on data source
* @return void
*/
public function setSource($tableName) {
$this->setDataSource($this->useDbConfig);
$db =& ConnectionManager::getDataSource($this->useDbConfig);
$db = ConnectionManager::getDataSource($this->useDbConfig);
$db->cacheSources = ($this->cacheSources && $db->cacheSources);
if ($db->isInterfaceSupported('listSources')) {
$sources = $db->listSources();
if (is_array($sources) && !in_array(strtolower($this->tablePrefix . $tableName), array_map('strtolower', $sources))) {
return $this->cakeError('missingTable', array(array(
'className' => $this->alias,
'table' => $this->tablePrefix . $tableName
)));
throw new MissingTableException($this->alias, $this->tablePrefix . $tableName);
}
$this->_schema = null;
}
$this->table = $this->useTable = $tableName;
$this->tableToModel[$this->table] = $this->alias;
$this->schema();
}
/**
@ -841,7 +886,7 @@ class Model extends Object {
$dateFields = array('Y' => 'year', 'm' => 'month', 'd' => 'day', 'H' => 'hour', 'i' => 'min', 's' => 'sec');
$timeFields = array('H' => 'hour', 'i' => 'min', 's' => 'sec');
$db =& ConnectionManager::getDataSource($this->useDbConfig);
$db = $this->getDataSource();
$format = $db->columns[$type]['format'];
$date = array();
@ -902,7 +947,7 @@ class Model extends Object {
*/
public function schema($field = false) {
if (!is_array($this->_schema) || $field === true) {
$db =& ConnectionManager::getDataSource($this->useDbConfig);
$db = $this->getDataSource();
$db->cacheSources = ($this->cacheSources && $db->cacheSources);
if ($db->isInterfaceSupported('describe') && $this->useTable !== false) {
$this->_schema = $db->describe($this, $field);
@ -944,7 +989,7 @@ class Model extends Object {
* @return string Column type
*/
public function getColumnType($column) {
$db =& ConnectionManager::getDataSource($this->useDbConfig);
$db = $this->getDataSource();
$cols = $this->schema();
$model = null;
@ -1231,7 +1276,7 @@ class Model extends Object {
return false;
}
$db =& ConnectionManager::getDataSource($this->useDbConfig);
$db = $this->getDataSource();
foreach ($dateFields as $updateCol) {
if ($this->hasField($updateCol) && !in_array($updateCol, $fields)) {
@ -1300,7 +1345,7 @@ class Model extends Object {
if (!empty($this->id)) {
$success = (bool)$db->update($this, $fields, $values);
} else {
$fInfo = $this->_schema[$this->primaryKey];
$fInfo = $this->schema($this->primaryKey);
$isUUID = ($fInfo['length'] == 36 &&
($fInfo['type'] === 'string' || $fInfo['type'] === 'binary')
);
@ -1361,10 +1406,11 @@ class Model extends Object {
if (isset($this->hasAndBelongsToMany[$assoc])) {
list($join) = $this->joinModel($this->hasAndBelongsToMany[$assoc]['with']);
$keyInfo = $this->{$join}->schema($this->{$join}->primaryKey);
$isUUID = !empty($this->{$join}->primaryKey) && (
$this->{$join}->_schema[$this->{$join}->primaryKey]['length'] == 36 && (
$this->{$join}->_schema[$this->{$join}->primaryKey]['type'] === 'string' ||
$this->{$join}->_schema[$this->{$join}->primaryKey]['type'] === 'binary'
$keyInfo['length'] == 36 && (
$keyInfo['type'] === 'string' ||
$keyInfo['type'] === 'binary'
)
);
@ -1548,7 +1594,7 @@ class Model extends Object {
if (empty($data)) {
$data = $this->data;
}
$db =& ConnectionManager::getDataSource($this->useDbConfig);
$db = $this->getDataSource();
$options = array_merge(array('validate' => 'first', 'atomic' => true), $options);
$this->validationErrors = $validationErrors = array();
@ -1753,8 +1799,7 @@ class Model extends Object {
* @link http://book.cakephp.org/view/1031/Saving-Your-Data
*/
function updateAll($fields, $conditions = true) {
$db =& ConnectionManager::getDataSource($this->useDbConfig);
return $db->update($this, $fields, null, $conditions);
return $this->getDataSource()->update($this, $fields, null, $conditions);
}
/**
@ -1773,7 +1818,7 @@ class Model extends Object {
$id = $this->id;
if ($this->exists() && $this->beforeDelete($cascade)) {
$db =& ConnectionManager::getDataSource($this->useDbConfig);
$db = $this->getDataSource();
$filters = $this->Behaviors->trigger($this, 'beforeDelete', array($cascade), array(
'break' => true, 'breakOn' => false
));
@ -1820,7 +1865,7 @@ class Model extends Object {
foreach (array_merge($this->hasMany, $this->hasOne) as $assoc => $data) {
if ($data['dependent'] === true && $cascade === true) {
$model =& $this->{$assoc};
$model = $this->{$assoc};
$conditions = array($model->escapeField($data['foreignKey']) => $id);
if ($data['conditions']) {
$conditions = array_merge((array)$data['conditions'], $conditions);
@ -1883,7 +1928,7 @@ class Model extends Object {
if (empty($conditions)) {
return false;
}
$db =& ConnectionManager::getDataSource($this->useDbConfig);
$db = $this->getDataSource();
if (!$cascade && !$callbacks) {
return $db->delete($this, $conditions);
@ -2056,7 +2101,7 @@ class Model extends Object {
}
}
if (!$db =& ConnectionManager::getDataSource($this->useDbConfig)) {
if (!$db = $this->getDataSource()) {
return false;
}
@ -2112,7 +2157,7 @@ class Model extends Object {
*/
function _findCount($state, $query, $results = array()) {
if ($state == 'before') {
$db =& ConnectionManager::getDataSource($this->useDbConfig);
$db = $this->getDataSource();
if (empty($query['fields'])) {
$query['fields'] = $db->calculate($this, 'count');
} elseif (is_string($query['fields']) && !preg_match('/count/i', $query['fields'])) {
@ -2312,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
*/
@ -2330,7 +2375,7 @@ class Model extends Object {
foreach ($this->__associations as $type) {
foreach ($this->{$type} as $key => $name) {
if (!empty($this->{$key}->__backAssociation)) {
if (property_exists($this, $key) && !empty($this->{$key}->__backAssociation)) {
$this->{$key}->resetAssociations();
}
}
@ -2391,7 +2436,7 @@ class Model extends Object {
*/
function query() {
$params = func_get_args();
$db =& ConnectionManager::getDataSource($this->useDbConfig);
$db = $this->getDataSource();
return call_user_func_array(array(&$db, 'query'), $params);
}
@ -2653,7 +2698,7 @@ class Model extends Object {
if (empty($field)) {
$field = $this->primaryKey;
}
$db =& ConnectionManager::getDataSource($this->useDbConfig);
$db = $this->getDataSource();
if (strpos($field, $db->name($alias) . '.') === 0) {
return $field;
}
@ -2725,8 +2770,7 @@ class Model extends Object {
* @return int Number of rows
*/
public function getNumRows() {
$db =& ConnectionManager::getDataSource($this->useDbConfig);
return $db->lastNumRows();
return $this->getDataSource()->lastNumRows();
}
/**
@ -2735,8 +2779,7 @@ class Model extends Object {
* @return int Number of rows
*/
public function getAffectedRows() {
$db =& ConnectionManager::getDataSource($this->useDbConfig);
return $db->lastAffected();
return $this->getDataSource()->lastAffected();
}
/**
@ -2751,9 +2794,9 @@ class Model extends Object {
if ($dataSource != null) {
$this->useDbConfig = $dataSource;
}
$db =& ConnectionManager::getDataSource($this->useDbConfig);
$db = ConnectionManager::getDataSource($this->useDbConfig);
if (!empty($oldConfig) && isset($db->config['prefix'])) {
$oldDb =& ConnectionManager::getDataSource($oldConfig);
$oldDb = ConnectionManager::getDataSource($oldConfig);
if (!isset($this->tablePrefix) || (!isset($oldDb->config['prefix']) || $this->tablePrefix == $oldDb->config['prefix'])) {
$this->tablePrefix = $db->config['prefix'];
@ -2773,9 +2816,13 @@ class Model extends Object {
*
* @return object A DataSource object
*/
public function &getDataSource() {
$db =& ConnectionManager::getDataSource($this->useDbConfig);
return $db;
public function getDataSource() {
static $configured = false;
if (!$configured && $this->useTable !== false) {
$configured = true;
$this->setSource($this->useTable);
}
return ConnectionManager::getDataSource($this->useDbConfig);
}
/**
@ -2841,6 +2888,7 @@ class Model extends Object {
*/
public function joinModel($assoc, $keys = array()) {
if (is_string($assoc)) {
list(, $assoc) = pluginSplit($assoc);
return array($assoc, array_keys($this->{$assoc}->schema()));
} elseif (is_array($assoc)) {
$with = key($assoc);
@ -2996,3 +3044,54 @@ class Model extends Object {
function __wakeup() {
}
}
/**
* Exception class to be thrown when a database table is not found in the datasource
*
*/
class MissingTableException extends RuntimeException {
/**
* The name of the model wanting to load the database table
*
* @var string
*/
protected $model;
/**
* The name of the missing table
*
* @var string
*/
protected $table;
/**
* Exception costructor
*
* @param string $model The name of the model wanting to load the database table
* @param string $table The name of the missing table
* @return void
*/
public function __construct($model, $table) {
$this->model = $model;
$this->$table = $table;
$message = sprintf(__('Database table %s for model %s was not found.'), $table, $model);
parent::__construct($message);
}
/**
* Returns the name of the model wanting to load the database table
*
* @return string
*/
public function getModel() {
return $this->model;
}
/**
* Returns the name of the missing table
*
* @return string
*/
public function getTable() {
return $this->table;
}
}

View file

@ -20,6 +20,10 @@
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
if (!class_exists('Router')) {
App::import('Core', 'Router');
}
/**
* Abstract base class for all other Helpers in CakePHP.
* Provides common methods and features.

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

@ -823,7 +823,7 @@ abstract class JsBaseEngineHelper extends AppHelper {
* @param array $options Array of options for the effect.
* @return string completed string with effect.
*/
abstract public function effect($name, $options);
abstract public function effect($name, $options = array());
/**
* Make an XHR request
@ -913,7 +913,7 @@ abstract class JsBaseEngineHelper extends AppHelper {
* @param array $options Array of options for the sortable. See above.
* @return string Completed sortable script.
*/
abstract public function sortable();
abstract public function sortable($options = array());
/**
* Create a slider UI widget. Comprised of a track and knob.
@ -935,7 +935,7 @@ abstract class JsBaseEngineHelper extends AppHelper {
*
* @return string Completed slider script
*/
abstract public function slider();
abstract public function slider($options = array());
/**
* Serialize the form attached to $selector.
* Pass `true` for $isForm if the current selection is a form element.
@ -950,7 +950,7 @@ abstract class JsBaseEngineHelper extends AppHelper {
* @param array $options options for serialization generation.
* @return string completed form serialization script
*/
abstract public function serializeForm();
abstract public function serializeForm($options = array());
/**
* Parse an options assoc array into an Javascript object literal.

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

@ -19,6 +19,7 @@
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::import('Shell', 'Shell', false);
App::import('Core', 'Controller');
if (!defined('DISABLE_AUTO_DISPATCH')) {
define('DISABLE_AUTO_DISPATCH', true);

View file

@ -283,7 +283,7 @@ class SchemaShellTest extends CakeTestCase {
$this->Shell->Schema->expects($this->at(0))->method('write')->will($this->returnValue(true));
$this->Shell->Schema->expects($this->at(1))->method('read');
$this->Shell->Schema->expects($this->at(1))->method('write')->with(array('schema data', 'file' => 'schema_1.php'));
$this->Shell->Schema->expects($this->at(1))->method('write')->with(array('schema data', 'file' => 'schema_0.php'));
$this->Shell->generate();
}
@ -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);
@ -406,7 +407,7 @@ class SchemaShellTest extends CakeTestCase {
$this->Shell->expects($this->any())->method('in')->will($this->returnValue('y'));
$this->Shell->create();
$db =& ConnectionManager::getDataSource('test_suite');
$db =& ConnectionManager::getDataSource('test');
$sources = $db->listSources();
$this->assertTrue(in_array($db->config['prefix'] . 'acos', $sources));
$this->assertFalse(in_array($db->config['prefix'] . 'aros', $sources));

View file

@ -39,18 +39,18 @@ require_once CAKE . 'console' . DS . 'libs' . DS . 'tasks' . DS . 'template.php
require_once CAKE . 'console' . DS . 'libs' . DS . 'tasks' . DS . 'test.php';
$imported = App::import('Model', 'Article');
$imported = $imported || App::import('Model', 'Comment');
$imported = $imported || App::import('Model', 'Tag');
$imported = App::import('Model', 'BakeArticle');
$imported = $imported || App::import('Model', 'BakeComment');
$imported = $imported || App::import('Model', 'BakeTag');
if (!$imported) {
define('ARTICLE_MODEL_CREATED', true);
App::import('Core', 'Model');
class Article extends Model {
public $name = 'Article';
public $hasMany = array('Comment');
public $hasAndBelongsToMany = array('Tag');
class BakeArticle extends Model {
public $name = 'BakeArticle';
public $hasMany = array('BakeComment');
public $hasAndBelongsToMany = array('BakeTag');
}
}
@ -69,7 +69,7 @@ class ControllerTaskTest extends CakeTestCase {
* @var array
* @access public
*/
public $fixtures = array('core.article', 'core.comment', 'core.articles_tag', 'core.tag');
public $fixtures = array('core.bake_article', 'core.bake_articles_bake_tag', 'core.bake_comment', 'core.bake_tag');
/**
* startTest method
@ -116,21 +116,26 @@ class ControllerTaskTest extends CakeTestCase {
* @return void
*/
public function testListAll() {
$count = count($this->Task->listAll('test_suite'));
if ($count != count($this->fixtures)) {
$this->markTestSkipped('Additional tables detected.');
}
$this->Task->connection = 'test_suite';
$this->Task->interactive = true;
$this->Task->expects($this->at(1))->method('out')->with('1. Articles');
$this->Task->expects($this->at(2))->method('out')->with('2. ArticlesTags');
$this->Task->expects($this->at(3))->method('out')->with('3. Comments');
$this->Task->expects($this->at(4))->method('out')->with('4. Tags');
$this->Task->expects($this->at(1))->method('out')->with('1. BakeArticles');
$this->Task->expects($this->at(2))->method('out')->with('2. BakeArticlesBakeTags');
$this->Task->expects($this->at(3))->method('out')->with('3. BakeComments');
$this->Task->expects($this->at(4))->method('out')->with('4. BakeTags');
$expected = array('Articles', 'ArticlesTags', 'Comments', 'Tags');
$expected = array('BakeArticles', 'BakeArticlesBakeTags', 'BakeComments', 'BakeTags');
$result = $this->Task->listAll('test_suite');
$this->assertEqual($result, $expected);
$this->Task->interactive = false;
$result = $this->Task->listAll();
$expected = array('articles', 'articles_tags', 'comments', 'tags');
$expected = array('bake_articles', 'bake_articles_bake_tags', 'bake_comments', 'bake_tags');
$this->assertEqual($result, $expected);
}
@ -140,15 +145,20 @@ class ControllerTaskTest extends CakeTestCase {
* @return void
*/
public function testGetNameValidIndex() {
$count = count($this->Task->listAll('test_suite'));
if ($count != count($this->fixtures)) {
$this->markTestSkipped('Additional tables detected.');
}
$this->Task->interactive = true;
$this->Task->expects($this->at(5))->method('in')->will($this->returnValue(3));
$this->Task->expects($this->at(7))->method('in')->will($this->returnValue(1));
$result = $this->Task->getName('test_suite');
$expected = 'Comments';
$expected = 'BakeComments';
$this->assertEqual($result, $expected);
$this->Task->expects($this->at(7))->method('in')->will($this->returnValue(1));
$result = $this->Task->getName('test_suite');
$expected = 'Articles';
$expected = 'BakeArticles';
$this->assertEqual($result, $expected);
}
@ -159,8 +169,9 @@ class ControllerTaskTest extends CakeTestCase {
*/
function testGetNameInvalidIndex() {
$this->Task->interactive = true;
$this->Task->expects($this->at(5))->method('in')->will($this->returnValue(10));
$this->Task->expects($this->at(7))->method('in')->will($this->returnValue('q'));
$this->Task->expects($this->any())->method('in')
->will($this->onConsecutiveCalls(50, 'q'));
$this->Task->expects($this->once())->method('err');
$this->Task->expects($this->once())->method('_stop');
@ -272,22 +283,22 @@ class ControllerTaskTest extends CakeTestCase {
$this->Task->expects($this->any())->method('createFile')->will($this->returnValue(true));
$result = $this->Task->bake('Articles', '--actions--', $helpers, $components);
$this->assertPattern('/class ArticlesController extends AppController/', $result);
$this->assertPattern('/\$components \= array\(\'Acl\', \'Auth\'\)/', $result);
$this->assertPattern('/\$helpers \= array\(\'Ajax\', \'Time\'\)/', $result);
$this->assertPattern('/\-\-actions\-\-/', $result);
$this->assertContains('class ArticlesController extends AppController', $result);
$this->assertContains("\$components = array('Acl', 'Auth')", $result);
$this->assertContains("\$helpers = array('Ajax', 'Time')", $result);
$this->assertContains("--actions--", $result);
$result = $this->Task->bake('Articles', 'scaffold', $helpers, $components);
$this->assertPattern('/class ArticlesController extends AppController/', $result);
$this->assertPattern('/public \$scaffold/', $result);
$this->assertNoPattern('/helpers/', $result);
$this->assertNoPattern('/components/', $result);
$this->assertContains("class ArticlesController extends AppController", $result);
$this->assertContains("public \$scaffold", $result);
$this->assertNotContains('helpers', $result);
$this->assertNotContains('components', $result);
$result = $this->Task->bake('Articles', '--actions--', array(), array());
$this->assertPattern('/class ArticlesController extends AppController/', $result);
$this->assertNoPattern('/components/', $result);
$this->assertNoPattern('/helpers/', $result);
$this->assertPattern('/\-\-actions\-\-/', $result);
$this->assertContains('class ArticlesController extends AppController', $result);
$this->assertNotContains('components', $result);
$this->assertNotContains('helpers', $result);
$this->assertContains('--actions--', $result);
}
/**
@ -330,35 +341,35 @@ class ControllerTaskTest extends CakeTestCase {
if ($skip) {
return;
}
$result = $this->Task->bakeActions('Articles', null, true);
$result = $this->Task->bakeActions('BakeArticles', null, true);
$this->assertTrue(strpos($result, 'function index() {') !== false);
$this->assertTrue(strpos($result, '$this->Article->recursive = 0;') !== false);
$this->assertTrue(strpos($result, "\$this->set('articles', \$this->paginate());") !== false);
$this->assertContains('function index() {', $result);
$this->assertContains('$this->BakeArticle->recursive = 0;', $result);
$this->assertContains("\$this->set('bakeArticles', \$this->paginate());", $result);
$this->assertTrue(strpos($result, 'function view($id = null)') !== false);
$this->assertTrue(strpos($result, "\$this->Session->setFlash(__('Invalid article'));") !== false);
$this->assertTrue(strpos($result, "\$this->set('article', \$this->Article->read(null, \$id)") !== false);
$this->assertContains('function view($id = null)', $result);
$this->assertContains("\$this->Session->setFlash(__('Invalid bake article'));", $result);
$this->assertContains("\$this->set('bakeArticle', \$this->BakeArticle->read(null, \$id)", $result);
$this->assertTrue(strpos($result, 'function add()') !== false);
$this->assertTrue(strpos($result, 'if (!empty($this->data))') !== false);
$this->assertTrue(strpos($result, 'if ($this->Article->save($this->data))') !== false);
$this->assertTrue(strpos($result, "\$this->Session->setFlash(__('The article has been saved'));") !== false);
$this->assertContains('function add()', $result);
$this->assertContains('if (!empty($this->data))', $result);
$this->assertContains('if ($this->BakeArticle->save($this->data))', $result);
$this->assertContains("\$this->Session->setFlash(__('The bake article has been saved'));", $result);
$this->assertTrue(strpos($result, 'function edit($id = null)') !== false);
$this->assertTrue(strpos($result, "\$this->Session->setFlash(__('The article could not be saved. Please, try again.'));") !== false);
$this->assertContains('function edit($id = null)', $result);
$this->assertContains("\$this->Session->setFlash(__('The bake article could not be saved. Please, try again.'));", $result);
$this->assertTrue(strpos($result, 'function delete($id = null)') !== false);
$this->assertTrue(strpos($result, 'if ($this->Article->delete($id))') !== false);
$this->assertTrue(strpos($result, "\$this->Session->setFlash(__('Article deleted'));") !== false);
$this->assertContains('function delete($id = null)', $result);
$this->assertContains('if ($this->BakeArticle->delete($id))', $result);
$this->assertContains("\$this->Session->setFlash(__('Bake article deleted'));", $result);
$result = $this->Task->bakeActions('Articles', 'admin_', true);
$result = $this->Task->bakeActions('BakeArticles', 'admin_', true);
$this->assertTrue(strpos($result, 'function admin_index() {') !== false);
$this->assertTrue(strpos($result, 'function admin_add()') !== false);
$this->assertTrue(strpos($result, 'function admin_view($id = null)') !== false);
$this->assertTrue(strpos($result, 'function admin_edit($id = null)') !== false);
$this->assertTrue(strpos($result, 'function admin_delete($id = null)') !== false);
$this->assertContains('function admin_index() {', $result);
$this->assertContains('function admin_add()', $result);
$this->assertContains('function admin_view($id = null)', $result);
$this->assertContains('function admin_edit($id = null)', $result);
$this->assertContains('function admin_delete($id = null)', $result);
}
/**
@ -372,29 +383,29 @@ class ControllerTaskTest extends CakeTestCase {
if ($skip) {
return;
}
$result = $this->Task->bakeActions('Articles', null, false);
$result = $this->Task->bakeActions('BakeArticles', null, false);
$this->assertTrue(strpos($result, 'function index() {') !== false);
$this->assertTrue(strpos($result, '$this->Article->recursive = 0;') !== false);
$this->assertTrue(strpos($result, "\$this->set('articles', \$this->paginate());") !== false);
$this->assertContains('function index() {', $result);
$this->assertContains('$this->BakeArticle->recursive = 0;', $result);
$this->assertContains("\$this->set('bakeArticles', \$this->paginate());", $result);
$this->assertTrue(strpos($result, 'function view($id = null)') !== false);
$this->assertTrue(strpos($result, "\$this->flash(__('Invalid article'), array('action' => 'index'))") !== false);
$this->assertTrue(strpos($result, "\$this->set('article', \$this->Article->read(null, \$id)") !== false);
$this->assertContains('function view($id = null)', $result);
$this->assertContains("\$this->flash(__('Invalid bake article'), array('action' => 'index'))", $result);
$this->assertContains("\$this->set('bakeArticle', \$this->BakeArticle->read(null, \$id)", $result);
$this->assertTrue(strpos($result, 'function add()') !== false);
$this->assertTrue(strpos($result, 'if (!empty($this->data))') !== false);
$this->assertTrue(strpos($result, 'if ($this->Article->save($this->data))') !== false);
$this->assertContains('function add()', $result);
$this->assertContains('if (!empty($this->data))', $result);
$this->assertContains('if ($this->BakeArticle->save($this->data))', $result);
$this->assertTrue(strpos($result, "\$this->flash(__('The article has been saved.'), array('action' => 'index'))") !== false);
$this->assertContains("\$this->flash(__('The bake article has been saved.'), array('action' => 'index'))", $result);
$this->assertTrue(strpos($result, 'function edit($id = null)') !== false);
$this->assertTrue(strpos($result, "\$this->Article->Tag->find('list')") !== false);
$this->assertTrue(strpos($result, "\$this->set(compact('tags'))") !== false);
$this->assertContains('function edit($id = null)', $result);
$this->assertContains("\$this->BakeArticle->BakeTag->find('list')", $result);
$this->assertContains("\$this->set(compact('bakeTags'))", $result);
$this->assertTrue(strpos($result, 'function delete($id = null)') !== false);
$this->assertTrue(strpos($result, 'if ($this->Article->delete($id))') !== false);
$this->assertTrue(strpos($result, "\$this->flash(__('Article deleted'), array('action' => 'index'))") !== false);
$this->assertContains('function delete($id = null)', $result);
$this->assertContains('if ($this->BakeArticle->delete($id))', $result);
$this->assertContains("\$this->flash(__('Bake article deleted'), array('action' => 'index'))", $result);
}
/**
@ -407,8 +418,8 @@ class ControllerTaskTest extends CakeTestCase {
$this->Task->connection = 'test_suite';
$this->Task->interactive = false;
$this->Task->Test->expects($this->once())->method('bake')->with('Controller', 'Articles');
$this->Task->bakeTest('Articles');
$this->Task->Test->expects($this->once())->method('bake')->with('Controller', 'BakeArticles');
$this->Task->bakeTest('BakeArticles');
$this->assertEqual($this->Task->plugin, $this->Task->Test->plugin);
$this->assertEqual($this->Task->connection, $this->Task->Test->connection);
@ -421,6 +432,11 @@ class ControllerTaskTest extends CakeTestCase {
* @return void
*/
public function testInteractive() {
$count = count($this->Task->listAll('test_suite'));
if ($count != count($this->fixtures)) {
$this->markTestSkipped('Additional tables detected.');
}
$this->Task->connection = 'test_suite';
$this->Task->path = '/my/path/';
@ -437,10 +453,10 @@ class ControllerTaskTest extends CakeTestCase {
'y' // looks good?
));
$filename = '/my/path/articles_controller.php';
$filename = '/my/path/bake_articles_controller.php';
$this->Task->expects($this->once())->method('createFile')->with(
$filename,
new PHPUnit_Framework_Constraint_PCREMatch('/class ArticlesController/')
new PHPUnit_Framework_Constraint_PCREMatch('/class BakeArticlesController/')
);
$this->Task->execute();
}
@ -449,9 +465,13 @@ class ControllerTaskTest extends CakeTestCase {
* test Interactive mode.
*
* @return void
* @access public
*/
function testInteractiveAdminMethodsNotInteractive() {
$count = count($this->Task->listAll('test_suite'));
if ($count != count($this->fixtures)) {
$this->markTestSkipped('Additional tables detected.');
}
$this->Task->connection = 'test_suite';
$this->Task->interactive = true;
$this->Task->path = '/my/path/';
@ -473,10 +493,10 @@ class ControllerTaskTest extends CakeTestCase {
->method('getPrefix')
->will($this->returnValue('admin_'));
$filename = '/my/path/articles_controller.php';
$filename = '/my/path/bake_articles_controller.php';
$this->Task->expects($this->once())->method('createFile')->with(
$filename,
new PHPUnit_Framework_Constraint_PCREMatch('/class ArticlesController/')
new PHPUnit_Framework_Constraint_PCREMatch('/class BakeArticlesController/')
)->will($this->returnValue(true));
$result = $this->Task->execute();
@ -501,10 +521,10 @@ class ControllerTaskTest extends CakeTestCase {
$this->Task->expects($this->any())->method('_checkUnitTest')->will($this->returnValue(true));
$this->Task->Test->expects($this->once())->method('bake');
$filename = '/my/path/articles_controller.php';
$filename = '/my/path/bake_articles_controller.php';
$this->Task->expects($this->once())->method('createFile')->with(
$filename,
new PHPUnit_Framework_Constraint_PCREMatch('/class ArticlesController/')
new PHPUnit_Framework_Constraint_PCREMatch('/class BakeArticlesController/')
)->will($this->returnValue(true));
$this->Task->execute();
@ -523,9 +543,9 @@ class ControllerTaskTest extends CakeTestCase {
}
$this->Task->connection = 'test_suite';
$this->Task->path = '/my/path/';
$this->Task->args = array('Articles');
$this->Task->args = array('BakeArticles');
$filename = '/my/path/articles_controller.php';
$filename = '/my/path/bake_articles_controller.php';
$this->Task->expects($this->once())->method('createFile')->with(
$filename,
new PHPUnit_Framework_Constraint_PCREMatch('/\$scaffold/')
@ -541,7 +561,7 @@ class ControllerTaskTest extends CakeTestCase {
*/
static function nameVariations() {
return array(
array('Articles'), array('Article'), array('article'), array('articles')
array('BakeArticles'), array('BakeArticle'), array('bake_article'), array('bake_articles')
);
}
@ -561,7 +581,7 @@ class ControllerTaskTest extends CakeTestCase {
$this->Task->path = '/my/path/';
$this->Task->args = array($name);
$filename = '/my/path/articles_controller.php';
$filename = '/my/path/bake_articles_controller.php';
$this->Task->expects($this->once())->method('createFile')->with(
$filename, new PHPUnit_Framework_Constraint_PCREMatch('/\$scaffold/')
);
@ -581,9 +601,9 @@ class ControllerTaskTest extends CakeTestCase {
}
$this->Task->connection = 'test_suite';
$this->Task->path = '/my/path/';
$this->Task->args = array('Articles', 'public');
$this->Task->args = array('BakeArticles', 'public');
$filename = '/my/path/articles_controller.php';
$filename = '/my/path/bake_articles_controller.php';
$expected = new PHPUnit_Framework_Constraint_Not(new PHPUnit_Framework_Constraint_PCREMatch('/\$scaffold/'));
$this->Task->expects($this->once())->method('createFile')->with(
$filename, $expected
@ -605,9 +625,9 @@ class ControllerTaskTest extends CakeTestCase {
$this->Task->Project->expects($this->any())->method('getPrefix')->will($this->returnValue('admin_'));
$this->Task->connection = 'test_suite';
$this->Task->path = '/my/path/';
$this->Task->args = array('Articles', 'public', 'admin');
$this->Task->args = array('BakeArticles', 'public', 'admin');
$filename = '/my/path/articles_controller.php';
$filename = '/my/path/bake_articles_controller.php';
$this->Task->expects($this->once())->method('createFile')->with(
$filename, new PHPUnit_Framework_Constraint_PCREMatch('/admin_index/')
);
@ -628,9 +648,9 @@ class ControllerTaskTest extends CakeTestCase {
$this->Task->Project->expects($this->any())->method('getPrefix')->will($this->returnValue('admin_'));
$this->Task->connection = 'test_suite';
$this->Task->path = '/my/path/';
$this->Task->args = array('Articles', 'admin');
$this->Task->args = array('BakeArticles', 'admin');
$filename = '/my/path/articles_controller.php';
$filename = '/my/path/bake_articles_controller.php';
$this->Task->expects($this->once())->method('createFile')->with(
$filename, new PHPUnit_Framework_Constraint_PCREMatch('/admin_index/')
);

View file

@ -149,9 +149,6 @@ class ExtractTaskTest extends CakeTestCase {
$Folder = new Folder($path);
$Folder->delete();
}
function getTests() {
return array('start', 'startCase', 'testExtractMultiplePaths', 'endCase', 'end');
}
/**
* test extract can read more than one path.
@ -169,8 +166,8 @@ class ExtractTaskTest extends CakeTestCase {
TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'views' . DS . 'posts';
$this->Task->params['output'] = $path . DS;
$this->Task->Dispatch->expectNever('stderr');
$this->Task->Dispatch->expectNever('_stop');
$this->Task->Dispatch->expects($this->never())->method('stderr');
$this->Task->Dispatch->expects($this->never())->method('_stop');
$this->Task->execute();
$result = file_get_contents($path . DS . 'default.pot');

View file

@ -341,10 +341,10 @@ class FixtureTaskTest extends CakeTestCase {
$filename = '/my/path/article_fixture.php';
$this->Task->expects($this->at(0))->method('createFile')
->with($filename, new PHPUnit_Framework_Constraint_PCREMatch('/Article/'));
->with($filename, new PHPUnit_Framework_Constraint_PCREMatch('/ArticleFixture/'));
$this->Task->expects($this->at(1))->method('createFile')
->with($filename, new PHPUnit_Framework_Constraint_PCREMatch('/\<\?php(.*)\?\>/ms'));
->with($filename, new PHPUnit_Framework_Constraint_PCREMatch('/\<\?php/ms'));
$result = $this->Task->generateFixtureFile('Article', array());

View file

@ -112,6 +112,10 @@ class ModelTaskTest extends CakeTestCase {
* @return void
*/
public function testListAll() {
$count = count($this->Task->listAll('test_suite'));
if ($count != count($this->fixtures)) {
$this->markTestSkipped('Additional tables detected.');
}
$this->_useMockedOut();
$this->Task->expects($this->at(1))->method('out')->with('1. Article');
@ -153,8 +157,12 @@ class ModelTaskTest extends CakeTestCase {
* @return void
*/
function testGetNameValidOption() {
$this->Task->expects($this->at(0))->method('in')->will($this->returnValue(1));
$this->Task->expects($this->at(1))->method('in')->will($this->returnValue(4));
$count = count($this->Task->listAll('test_suite'));
if ($count != count($this->fixtures)) {
$this->markTestSkipped('Additional tables detected.');
}
$this->Task->expects($this->any())->method('in')->will($this->onConsecutiveCalls(1, 4));
$result = $this->Task->getName('test_suite');
$expected = 'Article';
@ -171,8 +179,7 @@ class ModelTaskTest extends CakeTestCase {
* @return void
*/
function testGetNameWithOutOfBoundsOption() {
$this->Task->expects($this->at(0))->method('in')->will($this->returnValue(10));
$this->Task->expects($this->at(2))->method('in')->will($this->returnValue(1));
$this->Task->expects($this->any())->method('in')->will($this->onConsecutiveCalls(10, 1));
$this->Task->expects($this->once())->method('err');
$result = $this->Task->getName('test_suite');
@ -196,8 +203,7 @@ class ModelTaskTest extends CakeTestCase {
* @return void
*/
function testGetTableNameCustom() {
$this->Task->expects($this->at(0))->method('in')->will($this->returnValue('n'));
$this->Task->expects($this->at(1))->method('in')->will($this->returnValue('my_table'));
$this->Task->expects($this->any())->method('in')->will($this->onConsecutiveCalls('n', 'my_table'));
$result = $this->Task->getTable('Article', 'test_suite');
$expected = 'my_table';
$this->assertEqual($result, $expected);
@ -287,8 +293,8 @@ class ModelTaskTest extends CakeTestCase {
function testInteractiveFieldValidationWithRegexp() {
$this->Task->initValidations();
$this->Task->interactive = true;
$this->Task->expects($this->at(0))->method('in')->will($this->returnValue('/^[a-z]{0,9}$/'));
$this->Task->expects($this->at(1))->method('in')->will($this->returnValue('n'));
$this->Task->expects($this->any())->method('in')
->will($this->onConsecutiveCalls('/^[a-z]{0,9}$/', 'n'));
$result = $this->Task->fieldValidation('text', array('type' => 'string', 'length' => 10, 'null' => false));
$expected = array('a_z_0_9' => '/^[a-z]{0,9}$/');
@ -402,8 +408,9 @@ class ModelTaskTest extends CakeTestCase {
'id' => array(), 'tagname' => array(), 'body' => array(),
'created' => array(), 'modified' => array()
);
$this->Task->expects($this->at(0))->method('in')->will($this->returnValue('y'));
$this->Task->expects($this->at(1))->method('in')->will($this->returnValue(2));
$this->Task->expects($this->any())->method('in')
->will($this->onConsecutiveCalls('y', 2));
$result = $this->Task->findDisplayField($fields);
$this->assertEqual($result, 'tagname');
}
@ -501,6 +508,11 @@ class ModelTaskTest extends CakeTestCase {
* @return void
*/
public function testHasAndBelongsToManyGeneration() {
$count = count($this->Task->listAll('test_suite'));
if ($count != count($this->fixtures)) {
$this->markTestSkipped('Additional tables detected.');
}
$model = new Model(array('ds' => 'test_suite', 'name' => 'Article'));
$this->Task->connection = 'test_suite';
$this->Task->listAll();
@ -831,6 +843,11 @@ STRINGEND;
* @return void
*/
public function testExecuteIntoAll() {
$count = count($this->Task->listAll('test_suite'));
if ($count != count($this->fixtures)) {
$this->markTestSkipped('Additional tables detected.');
}
$this->Task->connection = 'test_suite';
$this->Task->path = '/my/path/';
$this->Task->args = array('all');
@ -871,6 +888,11 @@ STRINGEND;
* @return void
*/
function testSkipTablesAndAll() {
$count = count($this->Task->listAll('test_suite'));
if ($count != count($this->fixtures)) {
$this->markTestSkipped('Additional tables detected.');
}
$this->Task->connection = 'test_suite';
$this->Task->path = '/my/path/';
$this->Task->args = array('all');
@ -905,6 +927,11 @@ STRINGEND;
* @return void
*/
public function testExecuteIntoInteractive() {
$count = count($this->Task->listAll('test_suite'));
if ($count != count($this->fixtures)) {
$this->markTestSkipped('Additional tables detected.');
}
$this->Task->connection = 'test_suite';
$this->Task->path = '/my/path/';
$this->Task->interactive = true;
@ -948,8 +975,9 @@ STRINGEND;
$this->Task->expects($this->once())->method('_stop');
$this->Task->expects($this->once())->method('err');
$this->Task->expects($this->at(0))->method('in')->will($this->returnValue('Foobar'));
$this->Task->expects($this->at(1))->method('in')->will($this->returnValue('y'));
$this->Task->expects($this->any())->method('in')
->will($this->onConsecutiveCalls('Foobar', 'y'));
$this->Task->execute();
}
}

View file

@ -0,0 +1,119 @@
<?php
/**
* TestSuiteShell test case
*
* 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.tests.libs
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::import('Shell', 'Shell', false);
if (!defined('DISABLE_AUTO_DISPATCH')) {
define('DISABLE_AUTO_DISPATCH', true);
}
if (!class_exists('ShellDispatcher')) {
ob_start();
$argv = false;
require CAKE . 'console' . DS . 'cake.php';
ob_end_clean();
}
require_once CAKE . 'console' . DS . 'libs' . DS . 'testsuite.php';
class TestSuiteShellTest extends CakeTestCase {
/**
* setUp test case
*
* @return void
*/
public function setUp() {
$this->Dispatcher = $this->getMock(
'ShellDispatcher',
array('getInput', 'stdout', 'stderr', '_stop', '_initEnvironment')
);
$this->Shell = $this->getMock(
'TestSuiteShell',
array('in', 'out', 'hr', 'help', 'error', 'err', '_stop', 'initialize', 'run'),
array(&$this->Dispatcher)
);
$this->Shell->Dispatch->shellPaths = App::path('shells');
}
/**
* tearDown method
*
* @return void
*/
public function tearDown() {
unset($this->Dispatch, $this->Shell);
}
/**
* test available list of test cases for an empty category
*
* @return void
*/
public function testAvailableWithEmptyList() {
$this->Shell->startup();
$this->Shell->args = array('unexistant-category');
$this->Shell->expects($this->at(0))->method('out')->with(__("No test cases available \n\n"));
$this->Shell->expects($this->once())->method('help');
$this->Shell->available();
}
/**
* test available list of test cases for core category
*
* @return void
*/
public function testAvailableCoreCategory() {
$this->Shell->startup();
$this->Shell->args = array('core');
$this->Shell->expects($this->at(0))->method('out')->with('Core Test Cases:');
$this->Shell->expects($this->at(1))->method('out')
->with(new PHPUnit_Framework_Constraint_PCREMatch('/\[1\].*/'));
$this->Shell->expects($this->at(2))->method('out')
->with(new PHPUnit_Framework_Constraint_PCREMatch('/\[2\].*/'));
$this->Shell->expects($this->once())->method('in')
->with(__('What test case would you like to run?'), null, 'q')
->will($this->returnValue('1'));
$this->Shell->expects($this->once())->method('run');
$this->Shell->available();
$this->assertEquals($this->Shell->args, array('core', 'Basics'));
}
/**
* Tests that correct option for test runner are passed
*
* @return void
*/
public function testRunnerOptions() {
$this->Shell->startup();
$this->Shell->args = array('core', 'Basics');
$this->Shell->params = array('filter' => 'myFilter', '-colors' => null, '-verbose' => null);
$this->Shell->expects($this->once())->method('run')
->with(
array('app' => false, 'plugin' => null, 'output' => 'text', 'case' => 'basics'),
array('--colors', '--verbose', '--filter', 'myFilter')
);
$this->Shell->main();
}
}

View file

@ -69,6 +69,15 @@ class TestDispatcher extends Dispatcher {
$this->stopped = true;
return true;
}
/**
* header method
*
* @return void
*/
public function header() {
}
}
/**
@ -1361,20 +1370,20 @@ class DispatcherTest extends CakeTestCase {
$expected = "alert('plugin one nested js file');";
$this->assertEqual($result, $expected);
Configure::write('debug', $debug);
//reset the header content-type without page can render as plain text.
header('Content-type: text/html');
//reset the
ob_start();
$Dispatcher->asset('test_plugin/css/unknown.extension');
$result = ob_get_clean();
$this->assertEqual('Testing a file with unknown extension to mime mapping.', $result);
header('Content-type: text/html');
ob_start();
$Dispatcher->asset('test_plugin/css/theme_one.htc');
$result = ob_get_clean();
$this->assertEqual('htc file', $result);
header('Content-type: text/html');
}
/**
@ -1395,7 +1404,7 @@ class DispatcherTest extends CakeTestCase {
$result = ob_get_clean();
$this->assertTrue($Dispatcher->stopped);
header('HTTP/1.1 200 Ok');
}
/**

View file

@ -206,7 +206,7 @@ class CacheTest extends CakeTestCase {
Cache::write('test_somthing', 'this is the test data', 'tests');
$expected = array(
'path' => TMP . 'sessions',
'path' => TMP . 'sessions' . DS,
'prefix' => 'cake_',
'lock' => false,
'serialize' => true,
@ -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

@ -215,7 +215,7 @@ class FileEngineTest extends CakeTestCase {
$this->assertFalse(file_exists(CACHE . 'cake_serialize_test2'));
$this->assertFalse(file_exists(CACHE . 'cake_serialize_test3'));
Cache::config('default', array('engine' => 'File', 'path' => CACHE . 'views'));
Cache::config('default', array('engine' => 'File', 'path' => CACHE . 'views' . DS));
$data = 'this is a test of the emergency broadcasting system';
$write = Cache::write('controller_view_1', $data);

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;
}
}
}
/**
@ -463,6 +473,35 @@ class ControllerTest extends CakeTestCase {
unset($Controller);
}
/**
* testLoadModel method from a plugin controller
*
* @access public
* @return void
*/
function testLoadModelInPlugins() {
App::build(array(
'plugins' => array(TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'plugins' . DS),
'controllers' => array(TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'controllers' . DS),
'models' => array(TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'models' . DS)
));
App::import('Controller', 'TestPlugin.TestPlugin');
$Controller = new TestPluginController();
$Controller->plugin = 'TestPlugin';
$Controller->uses = false;
$this->assertFalse(isset($Controller->Comment));
$result = $Controller->loadModel('Comment');
$this->assertTrue($result);
$this->assertType('Comment', $Controller->Comment);
$this->assertTrue(in_array('Comment', $Controller->modelNames));
ClassRegistry::flush();
unset($Controller);
}
/**
* testConstructClasses method
*
@ -925,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

@ -272,6 +272,9 @@ class TestBehavior extends ModelBehavior {
* @return void
*/
function beforeTest(&$model) {
if (!isset($model->beforeTestResult)) {
$model->beforeTestResult = array();
}
$model->beforeTestResult[] = strtolower(get_class($this));
return strtolower(get_class($this));
}

View file

@ -50,6 +50,99 @@ class DboMock extends DboSource {
*/
class ModelIntegrationTest extends BaseModelTest {
/**
* testAssociationLazyLoading
*
* @group lazyloading
* @return void
*/
public function testAssociationLazyLoading() {
$this->loadFixtures('ArticleFeaturedsTags');
$Article = new ArticleFeatured();
$this->assertTrue(isset($Article->belongsTo['User']));
$this->assertFalse(property_exists($Article, 'User'));
$this->assertType('User', $Article->User);
$this->assertTrue(isset($Article->belongsTo['Category']));
$this->assertFalse(property_exists($Article, 'Category'));
$this->assertTrue(isset($Article->Category));
$this->assertType('Category', $Article->Category);
$this->assertTrue(isset($Article->hasMany['Comment']));
$this->assertFalse(property_exists($Article, 'Comment'));
$this->assertTrue(isset($Article->Comment));
$this->assertType('Comment', $Article->Comment);
$this->assertTrue(isset($Article->hasAndBelongsToMany['Tag']));
//There was not enough information to setup the association (joinTable and associationForeignKey)
//so the model was not lazy loaded
$this->assertTrue(property_exists($Article, 'Tag'));
$this->assertTrue(isset($Article->Tag));
$this->assertType('Tag', $Article->Tag);
$this->assertFalse(property_exists($Article, 'ArticleFeaturedsTag'));
$this->assertType('AppModel', $Article->ArticleFeaturedsTag);
$this->assertEquals($Article->hasAndBelongsToMany['Tag']['joinTable'], 'article_featureds_tags');
$this->assertEquals($Article->hasAndBelongsToMany['Tag']['associationForeignKey'], 'tag_id');
}
/**
* testAssociationLazyLoadWithHABTM
*
* @group lazyloading
* @return void
*/
public function testAssociationLazyLoadWithHABTM() {
$this->loadFixtures('FruitsUuidTag', 'ArticlesTag');
$Article = new ArticleB();
$this->assertTrue(isset($Article->hasAndBelongsToMany['TagB']));
$this->assertFalse(property_exists($Article, 'TagB'));
$this->assertType('TagB', $Article->TagB);
$this->assertFalse(property_exists($Article, 'ArticlesTag'));
$this->assertType('AppModel', $Article->ArticlesTag);
$UuidTag = new UuidTag();
$this->assertTrue(isset($UuidTag->hasAndBelongsToMany['Fruit']));
$this->assertFalse(property_exists($UuidTag, 'Fruit'));
$this->assertFalse(property_exists($UuidTag, 'FruitsUuidTag'));
$this->assertTrue(isset($UuidTag->Fruit));
$this->assertFalse(property_exists($UuidTag, 'FruitsUuidTag'));
$this->assertTrue(isset($UuidTag->FruitsUuidTag));
$this->assertType('FruitsUuidTag', $UuidTag->FruitsUuidTag);
}
/**
* testAssociationLazyLoadWithBindModel
*
* @group lazyloading
* @return void
*/
public function testAssociationLazyLoadWithBindModel() {
$this->loadFixtures('Article', 'User');
$Article = new ArticleB();
$this->assertFalse(isset($Article->belongsTo['User']));
$this->assertFalse(property_exists($Article, 'User'));
$Article->bindModel(array('belongsTo' => array('User')));
$this->assertTrue(isset($Article->belongsTo['User']));
$this->assertFalse(property_exists($Article, 'User'));
$this->assertType('User', $Article->User);
}
/**
* Tests that creating a model with no existent database table associated will throw an exception
*
* @expectedException MissingTableException
* @return void
*/
public function testMissingTable() {
$Article = new ArticleB(false, uniqid());
$Article->schema();
}
/**
* testPkInHAbtmLinkModelArticleB
*
@ -96,7 +189,7 @@ class ModelIntegrationTest extends BaseModelTest {
$this->assertEqual($TestModel->ContentAccount->primaryKey, 'iContentAccountsId');
//test conformant models with no PK in the join table
$this->loadFixtures('Article', 'Tag', 'User', 'Comment', 'Attachment', 'Syfile', 'Image', 'Item', 'Portfolio', 'ItemsPortfolio');
$this->loadFixtures('Article', 'Tag');
$TestModel2 = new Article();
$this->assertEqual($TestModel2->ArticlesTag->primaryKey, 'article_id');
@ -874,7 +967,7 @@ class ModelIntegrationTest extends BaseModelTest {
* @return void
*/
function testLoadModelSecondIteration() {
$this->loadFixtures('Message', 'Thread', 'Bid');
$this->loadFixtures('Apple', 'Message', 'Thread', 'Bid');
$model = new ModelA();
$this->assertIsA($model,'ModelA');
@ -1063,7 +1156,7 @@ class ModelIntegrationTest extends BaseModelTest {
* @return void
*/
function testGetAssociated() {
$this->loadFixtures('Article', 'Category');
$this->loadFixtures('Article', 'Tag');
$Article = ClassRegistry::init('Article');
$assocTypes = array('hasMany', 'hasOne', 'belongsTo', 'hasAndBelongsToMany');
@ -1117,6 +1210,7 @@ class ModelIntegrationTest extends BaseModelTest {
'foreignKey' => false,
'className' => 'AssociationTest2',
'with' => 'JoinAsJoinB',
'dynamicWith' => true,
'associationForeignKey' => 'join_b_id',
'conditions' => '', 'fields' => '', 'order' => '', 'limit' => '', 'offset' => '',
'finderQuery' => '', 'deleteQuery' => '', 'insertQuery' => ''
@ -1187,6 +1281,7 @@ class ModelIntegrationTest extends BaseModelTest {
'className' => 'Tag',
'joinTable' => 'article_featureds_tags',
'with' => 'ArticleFeaturedsTag',
'dynamicWith' => true,
'foreignKey' => 'article_featured_id',
'associationForeignKey' => 'tag_id',
'conditions' => '',
@ -1215,7 +1310,7 @@ class ModelIntegrationTest extends BaseModelTest {
* @return void
*/
function testConstruct() {
$this->loadFixtures('Post', 'Comment');
$this->loadFixtures('Post');
$TestModel = ClassRegistry::init('MergeVarPluginPost');
$this->assertEqual($TestModel->actsAs, array('Containable', 'Tree'));

View file

@ -4571,7 +4571,7 @@ class ModelReadTest extends BaseModelTest {
* @return void
*/
function testBindMultipleTimes() {
$this->loadFixtures('User', 'Comment', 'Article');
$this->loadFixtures('User', 'Comment', 'Article', 'Tag', 'ArticlesTag');
$TestModel = new User();
$result = $TestModel->hasMany;
@ -4587,6 +4587,7 @@ class ModelReadTest extends BaseModelTest {
$result = $TestModel->find('all', array(
'fields' => 'User.id, User.user'
));
$expected = array(
array(
'User' => array(
@ -4654,7 +4655,9 @@ class ModelReadTest extends BaseModelTest {
),
array(
'User' => array(
'id' => '4', 'user' => 'garrett'),
'id' => '4',
'user' => 'garrett'
),
'Items' => array(
array(
'id' => '2',
@ -4730,6 +4733,58 @@ class ModelReadTest extends BaseModelTest {
),
'Items' => array()
));
$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);
}
@ -4752,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
*
@ -6418,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

@ -1483,7 +1483,7 @@ class ModelWriteTest extends BaseModelTest {
$this->loadFixtures('JoinA', 'JoinC', 'JoinAC', 'JoinB', 'JoinAB');
$TestModel = new JoinA();
$TestModel->hasBelongsToMany['JoinC']['unique'] = true;
$TestModel->hasBelongsToMany = array('JoinC' => array('unique' => true));
$data = array(
'JoinA' => array(
'id' => 1,
@ -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
@ -2957,14 +2957,21 @@ class ModelWriteTest extends BaseModelTest {
function testSaveAllTransactionNoRollback() {
$this->loadFixtures('Post');
Mock::generate('DboSource', 'MockTransactionDboSource');
$this->getMock('DboSource', array(), array(), 'MockTransactionDboSource');
$db = ConnectionManager::create('mock_transaction', array(
'datasource' => 'MockTransactionDbo',
));
$db->expectOnce('rollback');
$db->expects($this->at(2))
->method('isInterfaceSupported')
->with('describe')
->will($this->returnValue(true));
$Post =& new Post();
$Post->useDbConfig = 'mock_transaction';
$db->expects($this->once())
->method('describe')
->will($this->returnValue(array()));
$db->expects($this->once())->method('rollback');
$Post = new Post('mock_transaction');
$Post->validate = array(
'title' => array('rule' => array('notEmpty'))
@ -2994,7 +3001,7 @@ class ModelWriteTest extends BaseModelTest {
array('author_id' => 1, 'title' => '')
);
$ts = date('Y-m-d H:i:s');
$this->assertEquals($TestModel->saveAll($data), array());
$this->assertFalse($TestModel->saveAll($data));
$result = $TestModel->find('all', array('recursive' => -1));
$expected = array(
@ -3063,7 +3070,7 @@ class ModelWriteTest extends BaseModelTest {
array('author_id' => 1, 'title' => 'New Sixth Post')
);
$ts = date('Y-m-d H:i:s');
$this->assertEquals($TestModel->saveAll($data), array());
$this->assertFalse($TestModel->saveAll($data));
$result = $TestModel->find('all', array('recursive' => -1));
$expected = array(
@ -3261,7 +3268,7 @@ class ModelWriteTest extends BaseModelTest {
'body' => 'Trying to get away with an empty title'
));
$result = $TestModel->saveAll($data);
$this->assertEqual($result, array());
$this->assertFalse($result);
$result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC'));
$errors = array(1 => array('title' => 'This field cannot be left blank'));
@ -3347,7 +3354,7 @@ class ModelWriteTest extends BaseModelTest {
'title' => '',
'body' => 'Trying to get away with an empty title'
));
$this->assertEquals($TestModel->saveAll($data, array('validate' => 'first')), array());
$this->assertFalse($TestModel->saveAll($data, array('validate' => 'first')));
$result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC'));
$this->assertEqual($result, $expected);

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

@ -52,13 +52,13 @@ class OptionEngineHelper extends JsBaseEngineHelper {
function event($type, $callback, $options = array()) {}
function domReady($functionBody) {}
function each($callback) {}
function effect($name, $options) {}
function effect($name, $options = array()) {}
function request($url, $options = array()) {}
function drag($options = array()) {}
function drop($options = array()) {}
function sortable() {}
function slider() {}
function serializeForm() {}
function sortable($options = array()) {}
function slider($options = array()) {}
function serializeForm($options = array()) {}
}
/**

View file

@ -17,7 +17,9 @@
* @since CakePHP(tm) v 1.2.0.4206
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
*/
App::import('Core', array('Theme', 'Controller'));
App::import('View', 'View');
App::import('View', 'Theme');
App::import('Core', 'Controller');
if (!class_exists('ErrorHandler')) {
App::import('Core', array('Error'));
@ -298,9 +300,6 @@ class ThemeViewTest extends CakeTestCase {
* @return void
*/
function testMemoryLeakInPaths() {
if ($this->skipIf(!function_exists('memory_get_usage'), 'No memory measurement function, cannot test for possible memory leak. %s')) {
return;
}
$this->Controller->plugin = null;
$this->Controller->name = 'Posts';
$this->Controller->viewPath = 'posts';

View file

@ -0,0 +1,59 @@
<?php
/**
* BakeArticleFixture
*
* PHP 5
*
* CakePHP(tm) Tests <http://book.cakephp.org/view/1196/Testing>
* Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The Open Group Test Suite License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests
* @package cake
* @subpackage cake.tests.fixtures
* @since CakePHP(tm) v 2.0
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
*/
/**
* Short description for class.
*
* @package cake
* @subpackage cake.tests.fixtures
*/
class BakeArticleFixture extends CakeTestFixture {
/**
* name property
*
* @var string
*/
public $name = 'BakeArticle';
/**
* fields property
*
* @var array
* @access public
*/
public $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary'),
'bake_user_id' => array('type' => 'integer', 'null' => false),
'title' => array('type' => 'string', 'null' => false),
'body' => 'text',
'published' => array('type' => 'string', 'length' => 1, 'default' => 'N'),
'created' => 'datetime',
'updated' => 'datetime'
);
/**
* records property
*
* @var array
* @access public
*/
public $records = array();
}

View file

@ -0,0 +1,56 @@
<?php
/**
* BakeCommentFixture
*
* PHP 5
*
* CakePHP(tm) Tests <http://book.cakephp.org/view/1196/Testing>
* 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://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests
* @package cake
* @subpackage cake.tests.fixtures
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* Short description for class.
*
* @package cake
* @subpackage cake.tests.fixtures
*/
class BakeArticlesBakeTagFixture extends CakeTestFixture {
/**
* name property
*
* @var string 'ArticlesTag'
* @access public
*/
public $name = 'BakeArticlesBakeTag';
/**
* fields property
*
* @var array
* @access public
*/
public $fields = array(
'bake_article_id' => array('type' => 'integer', 'null' => false),
'bake_tag_id' => array('type' => 'integer', 'null' => false),
'indexes' => array('UNIQUE_TAG' => array('column'=> array('bake_article_id', 'bake_tag_id'), 'unique'=>1))
);
/**
* records property
*
* @var array
* @access public
*/
public $records = array();
}

View file

@ -0,0 +1,60 @@
<?php
/**
* BakeCommentFixture
*
* PHP 5
*
* CakePHP(tm) Tests <http://book.cakephp.org/view/1196/Testing>
* 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://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests
* @package cake
* @subpackage cake.tests.fixtures
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* BakeCommentFixture fixture for testing bake
*
* @package cake
* @subpackage cake.tests.fixtures
*/
class BakeCommentFixture extends CakeTestFixture {
/**
* name property
*
* @var string 'Comment'
* @access public
*/
public $name = 'BakeComment';
/**
* fields property
*
* @var array
* @access public
*/
public $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary'),
'bake_article_id' => array('type' => 'integer', 'null'=>false),
'bake_user_id' => array('type' => 'integer', 'null'=>false),
'comment' => 'text',
'published' => array('type' => 'string', 'length' => 1, 'default' => 'N'),
'created' => 'datetime',
'updated' => 'datetime'
);
/**
* records property
*
* @var array
* @access public
*/
public $records = array();
}

View file

@ -0,0 +1,57 @@
<?php
/**
* BakeTagFixture
*
* PHP 5
*
* CakePHP(tm) Tests <http://book.cakephp.org/view/1196/Testing>
* 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://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests
* @package cake
* @subpackage cake.tests.fixtures
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* Short description for class.
*
* @package cake
* @subpackage cake.tests.fixtures
*/
class BakeTagFixture extends CakeTestFixture {
/**
* name property
*
* @var string 'Tag'
* @access public
*/
public $name = 'BakeTag';
/**
* fields property
*
* @var array
* @access public
*/
public $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary'),
'tag' => array('type' => 'string', 'null' => false),
'created' => 'datetime',
'updated' => 'datetime'
);
/**
* records property
*
* @var array
* @access public
*/
public $records = array();
}

View file

@ -118,7 +118,21 @@ class CakeTestSuiteDispatcher {
*
* @return void
*/
function _checkPHPUnit() {
protected function _checkPHPUnit() {
$found = $this->loadTestFramework();
if (!$found) {
$baseDir = $this->_baseDir;
include CAKE_TESTS_LIB . 'templates/phpunit.php';
exit();
}
}
/**
* Checks for the existence of the test framework files
*
* @return boolean true if found, false otherwise
*/
public function loadTestFramework() {
$found = $path = null;
if (@include 'PHPUnit' . DS . 'Framework.php') {
@ -136,15 +150,11 @@ class CakeTestSuiteDispatcher {
$found = include 'PHPUnit' . DS . 'Framework.php';
}
}
if (!$found) {
$baseDir = $this->_baseDir;
include CAKE_TESTS_LIB . 'templates/phpunit.php';
exit();
}
if ($found) {
PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'DEFAULT');
}
return $found;
}
/**
* Checks for the xdebug extension required to do code coverage. Displays an error

View file

@ -159,7 +159,7 @@ class CakeBaseReporter implements PHPUnit_Framework_TestListener {
* @param float $time
*/
public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) {
$this->paintException($e);
$this->paintException($e, $test);
}
/**
@ -170,7 +170,7 @@ class CakeBaseReporter implements PHPUnit_Framework_TestListener {
* @param float $time
*/
public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) {
$this->paintFail($e);
$this->paintFail($e, $test);
}
/**

View file

@ -227,29 +227,16 @@ class CakeHtmlReporter extends CakeBaseReporter {
* the context of the other tests.
* @return void
*/
public function paintFail($message) {
$context = $message->getTrace();
$realContext = $context[3];
$class = new ReflectionClass($realContext['class']);
$deeper = false;
if ($class->getParentClass()) {
$deeper = $class->getParentClass()->getName() === 'PHPUnit_Framework_TestCase';
}
$deeper = $deeper || !$class->isSubclassOf('PHPUnit_Framework_TestCase');
if ($deeper) {
$realContext = $context[4];
$context = $context[3];
} else {
$context = $context[2];
}
public function paintFail($message, $test) {
$trace = $this->_getStackTrace($message);
$testName = get_class($test) . '(' . $test->getName() . ')';
echo "<li class='fail'>\n";
echo "<span>Failed</span>";
echo "<div class='msg'><pre>" . $this->_htmlEntities($message->toString()) . "</pre></div>\n";
echo "<div class='msg'>" . sprintf(__('File: %s'), $context['file']) . "</div>\n";
echo "<div class='msg'>" . sprintf(__('Method: %s'), $realContext['function']) . "</div>\n";
echo "<div class='msg'>" . sprintf(__('Line: %s'), $context['line']) . "</div>\n";
echo "<div class='msg'>" . sprintf(__('Test case: %s'), $testName) . "</div>\n";
echo "<div class='msg'>" . __('Stack trace:') . '<br />' . $trace . "</div>\n";
echo "</li>\n";
}
@ -278,7 +265,7 @@ class CakeHtmlReporter extends CakeBaseReporter {
* @param Exception $exception Exception to display.
* @return void
*/
public function paintException($exception) {
public function paintException($exception, $test) {
echo "<li class='fail'>\n";
echo "<span>Exception</span>";
$message = 'Unexpected exception of type [' . get_class($exception) .
@ -323,6 +310,27 @@ class CakeHtmlReporter extends CakeBaseReporter {
return htmlentities($message, ENT_COMPAT, $this->_characterSet);
}
/**
* Gets a formatted stack trace.
*
* @param Exception $e Exception to get a stack trace for.
* @return string Generated stack trace.
*/
protected function _getStackTrace(Exception $e) {
$trace = $e->getTrace();
$out = array();
foreach ($trace as $frame) {
if (isset($frame['file']) && isset($frame['line'])) {
$out[] = $frame['file'] . ' : ' . $frame['line'];
} elseif (isset($frame['class']) && isset($frame['function'])) {
$out[] = $frame['class'] . '::' . $frame['function'];
} else {
$out[] = '[internal]';
}
}
return implode('<br />', $out);
}
/**
* A test suite started.
*

View file

@ -75,6 +75,13 @@ class TestManager {
*/
protected $_fixtureManager = null;
/**
* Params to configure test runner
*
* @var CakeFixtureManager
*/
public $params = array();
/**
* Constructor for the TestManager class
*
@ -82,6 +89,8 @@ class TestManager {
*/
public function __construct($params = array()) {
require_once(CAKE_TESTS_LIB . 'cake_test_case.php');
$this->params = $params;
if (isset($params['app'])) {
$this->appTest = true;
}
@ -130,14 +139,7 @@ class TestManager {
* @return mixed Result of test case being run.
*/
public function runTestCase($testCaseFile, PHPUnit_Framework_TestListener $reporter, $codeCoverage = false) {
$testCaseFileWithPath = $this->_getTestsPath($reporter->params) . DS . $testCaseFile;
if (!file_exists($testCaseFileWithPath) || strpos($testCaseFileWithPath, '..')) {
throw new InvalidArgumentException(sprintf(__('Unable to load test file %s'), htmlentities($testCaseFile)));
}
$testSuite = $this->getTestSuite(sprintf(__('Individual test case: %s', true), $testCaseFile));
$testSuite->addTestFile($testCaseFileWithPath);
$this->loadCase($testCaseFile);
return $this->run($reporter, $codeCoverage);
}
@ -162,6 +164,28 @@ class TestManager {
return $result;
}
/**
* Loads a test case in a test suite, if the test suite is null it will create it
*
* @param string Test file path
* @param PHPUnit_Framework_TestSuite $suite the test suite to load the case in
* @throws InvalidArgumentException if test case file is not found
* @return PHPUnit_Framework_TestSuite the suite with the test case loaded
*/
public function loadCase($testCaseFile, PHPUnit_Framework_TestSuite $suite = null) {
$testCaseFileWithPath = $this->_getTestsPath($this->params) . DS . $testCaseFile;
if (!file_exists($testCaseFileWithPath) || strpos($testCaseFileWithPath, '..')) {
throw new InvalidArgumentException(sprintf(__('Unable to load test file %s'), htmlentities($testCaseFile)));
}
if (!$suite) {
$suite = $this->getTestSuite(sprintf(__('Individual test case: %s', true), $testCaseFile));
}
$suite->addTestFile($testCaseFileWithPath);
return $suite;
}
/**
* Adds all testcases in a given directory to a given GroupTest object
*
@ -313,7 +337,7 @@ class TestManager {
* @param string $name The name for the container test suite
* @return PHPUnit_Framework_TestSuite container test suite
*/
protected function getTestSuite($name = '') {
public function getTestSuite($name = '') {
if (!empty($this->_testSuite)) {
return $this->_testSuite;
}
@ -325,7 +349,7 @@ class TestManager {
*
* @return CakeFixtureManager fixture manager
*/
protected function getFixtureManager() {
public function getFixtureManager() {
if (!empty($this->_fixtureManager)) {
return $this->_fixtureManager;
}

View file

@ -0,0 +1,59 @@
<?php
/**
* TestRunner for CakePHP Test suite.
*
* 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.tests.libs
* @since CakePHP(tm) v 2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
require 'PHPUnit/TextUI/Command.php';
require_once 'test_manager.php';
PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'DEFAULT');
/**
* Class to customize loading of test suites from CLI
*
* @package cake
* @subpackage cake.cake.tests.lib
*/
class TestRunner extends PHPUnit_TextUI_Command {
/**
* Construct method
*
* @param array $params list of options to be used for this run
*/
public function __construct($params = array()) {
$this->_params = $params;
}
/**
* Sets the proper test suite to use and loads the test file in it.
* this method gets called as a callback from the parent class
*
* @return void
*/
protected function handleCustomTestSuite() {
$manager = new TestManager($this->_params);
if (!empty($this->_params['case'])) {
$this->arguments['test'] = $manager->getTestSuite();
$this->arguments['test']->setFixtureManager($manager->getFixtureManager());
$manager->loadCase($this->_params['case'] . '.test.php', $this->arguments['test']);
}
}
}

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) { }