diff --git a/app/View/elements/email/html/empty b/app/View/emails/html/empty similarity index 100% rename from app/View/elements/email/html/empty rename to app/View/emails/html/empty diff --git a/app/View/elements/email/text/empty b/app/View/emails/text/empty similarity index 100% rename from app/View/elements/email/text/empty rename to app/View/emails/text/empty diff --git a/app/View/layouts/email/html/empty b/app/View/layouts/emails/html/empty similarity index 100% rename from app/View/layouts/email/html/empty rename to app/View/layouts/emails/html/empty diff --git a/app/View/layouts/email/text/empty b/app/View/layouts/emails/text/empty similarity index 100% rename from app/View/layouts/email/text/empty rename to app/View/layouts/emails/text/empty diff --git a/app/config/core.php b/app/config/core.php index 3a7613b85..ea285689b 100644 --- a/app/config/core.php +++ b/app/config/core.php @@ -41,7 +41,7 @@ * * Options: * - * - `handler` - callback - The callback to handle errors. You can set this to any callback type, + * - `handler` - callback - The callback to handle errors. You can set this to any callback type, * including anonymous functions. * - `level` - int - The level of errors you are interested in capturing. * - `trace` - boolean - Include stack traces for errors in log files. @@ -55,14 +55,14 @@ )); /** - * Configure the Exception handler used for uncaught exceptions. By default, - * ErrorHandler::handleException() is used. It will display a HTML page for the exception, and - * while debug > 0, framework errors like Missing Controller will be displayed. When debug = 0, + * Configure the Exception handler used for uncaught exceptions. By default, + * ErrorHandler::handleException() is used. It will display a HTML page for the exception, and + * while debug > 0, framework errors like Missing Controller will be displayed. When debug = 0, * framework errors will be coerced into generic HTTP errors. * * Options: * - * - `handler` - callback - The callback to handle exceptions. You can set this to any callback type, + * - `handler` - callback - The callback to handle exceptions. You can set this to any callback type, * including anonymous functions. * - `renderer` - string - The class responsible for rendering uncaught exceptions. If you choose a custom class you * should place the file for that class in app/libs. This class needs to implement a render method. @@ -138,7 +138,7 @@ /** * Session configuration. * - * Contains an array of settings to use for session configuration. The defaults key is + * Contains an array of settings to use for session configuration. The defaults key is * used to define a default preset to use for sessions, any settings declared here will override * the settings of the default config. * @@ -147,14 +147,14 @@ * - `Session.name` - The name of the cookie to use. Defaults to 'CAKEPHP' * - `Session.timeout` - The number of minutes you want sessions to live for. This timeout is handled by CakePHP * - `Session.cookieTimeout` - The number of minutes you want session cookies to live for. - * - `Session.checkAgent` - Do you want the user agent to be checked when starting sessions? You might want to set the + * - `Session.checkAgent` - Do you want the user agent to be checked when starting sessions? You might want to set the * value to false, when dealing with older versions of IE, Chrome Frame or certain web-browsing devices and AJAX * - `Session.defaults` - The default configuration set to use as a basis for your session. * There are four builtins: php, cake, cache, database. * - `Session.handler` - Can be used to enable a custom session handler. Expects an array of of callables, * that can be used with `session_save_handler`. Using this option will automatically add `session.save_handler` * to the ini array. - * - `Session.autoRegenerate` - Enabling this setting, turns on automatic renewal of sessions, and + * - `Session.autoRegenerate` - Enabling this setting, turns on automatic renewal of sessions, and * sessionids that change frequently. See CakeSession::$requestCountdown. * - `Session.ini` - An associative array of additional ini values to set. * @@ -284,9 +284,13 @@ * */ -// Pick the caching engine to use. If APC is enabled use it. +/** + * Pick the caching engine to use. If APC is enabled use it. + * If running via cli - apc is disabled by default. ensure it's avaiable and enabled in this case + * + */ $engine = 'File'; -if (extension_loaded('apc')) { +if (extension_loaded('apc') && (php_sapi_name() !== 'cli' || ini_get('apc.enable_cli'))) { $engine = 'Apc'; } @@ -309,7 +313,7 @@ Cache::config('_cake_core_', array( )); /** - * Configure the cache for model, and datasource caches. This cache configuration + * Configure the cache for model, and datasource caches. This cache configuration * is used to store schema descriptions, and table listings in connections. */ Cache::config('_cake_model_', array( @@ -319,4 +323,3 @@ Cache::config('_cake_model_', array( 'serialize' => ($engine === 'File'), 'duration' => $duration )); - diff --git a/app/config/email.php.default b/app/config/email.php.default new file mode 100644 index 000000000..66c378f35 --- /dev/null +++ b/app/config/email.php.default @@ -0,0 +1,88 @@ + The name of a supported transport; valid options are as follows: + * mail - Send using PHP mail function + * smtp - Send using SMTP + * + * You can add custom transports (or override existing transports) by adding the + * appropriate file to app/Network/Email. Transports should be named 'YourTransport.php', + * where 'Your' is the name of the transport. + * + * from => + * The origin email. See CakeEmail::from() about the valid values + * + */ +class EmailConfig { + + public $default = array( + 'transport' => 'mail', + 'from' => 'you@localhost' + ); + + public $smtp = array( + 'transport' => 'smtp', + 'from' => array('My Site', 'site@localhost'), + 'host' => 'localhost', + 'port' => 25, + 'timeout' => 30, + 'username' => 'user', + 'password' => 'secret', + 'client' => null + ); + + public $fast = array( + 'from' => 'you@localhost', + 'sender' => null, + 'to' => null, + 'cc' => null, + 'bcc' => null, + 'replyTo' => null, + 'readReceipt' => null, + 'returnPath' => null, + 'messageId' => true, + 'subject' => null, + 'message' => null, + 'headers' => null, + 'viewRender' => null, + 'template' => false, + 'layout' => false, + 'viewVars' => null, + 'attachments' => null, + 'emailFormat' => null, + 'transport' => 'smtp', + 'host' => 'localhost', + 'port' => 25, + 'timeout' => 30, + 'username' => 'user', + 'password' => 'secret', + 'client' => null + ); + +} diff --git a/app/webroot/css.php b/app/webroot/css.php deleted file mode 100644 index 19ba84dc2..000000000 --- a/app/webroot/css.php +++ /dev/null @@ -1,93 +0,0 @@ -compress($data); - $ratio = 100 - (round(strlen($output) / strlen($data), 3) * 100); - $output = " /* file: $name, ratio: $ratio% */ " . $output; - return $output; - } -/** - * Write CSS cache - * - * @param unknown_type $path - * @param unknown_type $content - * @return unknown - */ - function write_css_cache($path, $content) { - if (!is_dir(dirname($path))) { - mkdir(dirname($path)); - } - $cache = new File($path); - return $cache->write($content); - } - - if (preg_match('|\.\.|', $url) || !preg_match('|^ccss/(.+)$|i', $url, $regs)) { - die('Wrong file name.'); - } - - $filename = 'css/' . $regs[1]; - $filepath = CSS . $regs[1]; - $cachepath = CACHE . 'css' . DS . str_replace(array('/','\\'), '-', $regs[1]); - - if (!file_exists($filepath)) { - die('Wrong file name.'); - } - - if (file_exists($cachepath)) { - $templateModified = filemtime($filepath); - $cacheModified = filemtime($cachepath); - - if ($templateModified > $cacheModified) { - $output = make_clean_css($filepath, $filename); - write_css_cache($cachepath, $output); - } else { - $output = file_get_contents($cachepath); - } - } else { - $output = make_clean_css($filepath, $filename); - write_css_cache($cachepath, $output); - $templateModified = time(); - } - - header("Date: " . date("D, j M Y G:i:s ", $templateModified) . 'GMT'); - header("Content-Type: text/css"); - header("Expires: " . gmdate("D, d M Y H:i:s", time() + DAY) . " GMT"); - header("Cache-Control: max-age=86400, must-revalidate"); // HTTP/1.1 - header("Pragma: cache"); // HTTP/1.0 - print $output; diff --git a/index.php b/index.php index 265576a3c..cda513cff 100644 --- a/index.php +++ b/index.php @@ -34,7 +34,7 @@ * Full path to the directory containing "cake". Do not add trailing directory separator */ if (!defined('CAKE_CORE_INCLUDE_PATH')) { - define('CAKE_CORE_INCLUDE_PATH', ROOT); + define('CAKE_CORE_INCLUDE_PATH', ROOT . DS . 'lib'); } /** diff --git a/lib/Cake/Cache/Cache.php b/lib/Cake/Cache/Cache.php index 2ffdeb007..ef87a9aff 100644 --- a/lib/Cake/Cache/Cache.php +++ b/lib/Cake/Cache/Cache.php @@ -96,7 +96,7 @@ class Cache { * - `duration` Specify how long items in this cache configuration last. * - `prefix` Prefix appended to all entries. Good for when you need to share a keyspace * with either another cache config or annother application. - * - `probability` Probability of hitting a cache gc cleanup. Setting to 0 will disable + * - `probability` Probability of hitting a cache gc cleanup. Setting to 0 will disable * cache::gc from ever being called automatically. * - `servers' Used by memcache. Give the address of the memcached servers to use. * - `compress` Used by memcache. Enables memcache's compressed format. @@ -298,7 +298,12 @@ class Cache { self::set(null, $config); if ($success === false && $value !== '') { trigger_error( - __d('cake_dev', "%s cache was unable to write '%s' to cache", $config, $key), + __d('cake_dev', + "%s cache was unable to write '%s' to %s cache", + $config, + $key, + self::$_engines[$config]->settings['engine'] + ), E_USER_WARNING ); } @@ -371,7 +376,7 @@ class Cache { * Decrement a number under the key and return decremented value. * * @param string $key Identifier for the data - * @param integer $offset How much to substract + * @param integer $offset How much to subtract * @param string $config Optional string configuration name. Defaults to 'default' * @return mixed new value, or false if the data doesn't exist, is not integer, * or if there was an error fetching it @@ -409,7 +414,7 @@ class Cache { * * @param string $key Identifier for the data * @param string $config name of the configuration to use. Defaults to 'default' - * @return boolean True if the value was succesfully deleted, false if it didn't exist or couldn't be removed + * @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed */ public static function delete($key, $config = 'default') { $settings = self::settings($config); @@ -435,7 +440,7 @@ class Cache { * * @param boolean $check if true will check expiration, otherwise delete all * @param string $config name of the configuration to use. Defaults to 'default' - * @return boolean True if the cache was succesfully cleared, false otherwise + * @return boolean True if the cache was successfully cleared, false otherwise */ public static function clear($check = false, $config = 'default') { if (!self::isInitialized($config)) { @@ -449,21 +454,20 @@ class Cache { /** * Check if Cache has initialized a working config for the given name. * - * @param string $engine Name of the engine, Defaults to default - * @param string $config Name of the configuration setting + * @param string $config name of the configuration to use. Defaults to 'default' * @return bool Whether or not the config name has been initialized. */ - public static function isInitialized($name = 'default') { + public static function isInitialized($config = 'default') { if (Configure::read('Cache.disable')) { return false; } - return isset(self::$_engines[$name]); + return isset(self::$_engines[$config]); } /** * Return the settings for the named cache engine. * - * @param string $engine Name of the configuration to get settings for. Defaults to 'default' + * @param string $name Name of the configuration to get settings for. Defaults to 'default' * @return array list of settings for this engine * @see Cache::config() * @access public @@ -497,8 +501,8 @@ abstract class CacheEngine { * * Called automatically by the cache frontend * - * @param array $params Associative array of parameters for the engine - * @return boolean True if the engine has been succesfully initialized, false if not + * @param array $settings Associative array of parameters for the engine + * @return boolean True if the engine has been successfully initialized, false if not */ public function init($settings = array()) { $this->settings = array_merge( @@ -526,7 +530,7 @@ abstract class CacheEngine { * @param string $key Identifier for the data * @param mixed $value Data to be cached * @param mixed $duration How long to cache for. - * @return boolean True if the data was succesfully cached, false on failure + * @return boolean True if the data was successfully cached, false on failure */ abstract public function write($key, $value, $duration); @@ -551,7 +555,7 @@ abstract class CacheEngine { * Decrement a number under the key and return decremented value * * @param string $key Identifier for the data - * @param integer $value How much to substract + * @param integer $offset How much to subtract * @return New incremented value, false otherwise */ abstract public function decrement($key, $offset = 1); @@ -560,7 +564,7 @@ abstract class CacheEngine { * Delete a key from the cache * * @param string $key Identifier for the data - * @return boolean True if the value was succesfully deleted, false if it didn't exist or couldn't be removed + * @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed */ abstract public function delete($key); @@ -568,7 +572,7 @@ abstract class CacheEngine { * Delete all keys from the cache * * @param boolean $check if true will check expiration, otherwise delete all - * @return boolean True if the cache was succesfully cleared, false otherwise + * @return boolean True if the cache was successfully cleared, false otherwise */ abstract public function clear($check); diff --git a/lib/Cake/Cache/Engine/ApcEngine.php b/lib/Cake/Cache/Engine/ApcEngine.php index 544a0c908..046e86d2c 100644 --- a/lib/Cake/Cache/Engine/ApcEngine.php +++ b/lib/Cake/Cache/Engine/ApcEngine.php @@ -31,7 +31,7 @@ class ApcEngine extends CacheEngine { * Called automatically by the cache frontend * To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array()); * - * @param array $setting array of setting for the engine + * @param array $settings array of setting for the engine * @return boolean True if the engine has been successfully initialized, false if not * @see CacheEngine::__defaults */ @@ -46,7 +46,7 @@ class ApcEngine extends CacheEngine { * @param string $key Identifier for the data * @param mixed $value Data to be cached * @param integer $duration How long to cache the data, in seconds - * @return boolean True if the data was succesfully cached, false on failure + * @return boolean True if the data was successfully cached, false on failure */ public function write($key, $value, $duration) { $expires = time() + $duration; @@ -74,7 +74,6 @@ class ApcEngine extends CacheEngine { * * @param string $key Identifier for the data * @param integer $offset How much to increment - * @param integer $duration How long to cache the data, in seconds * @return New incremented value, false otherwise */ public function increment($key, $offset = 1) { @@ -85,8 +84,7 @@ class ApcEngine extends CacheEngine { * Decrements the value of an integer cached key * * @param string $key Identifier for the data - * @param integer $offset How much to substract - * @param integer $duration How long to cache the data, in seconds + * @param integer $offset How much to subtract * @return New decremented value, false otherwise */ public function decrement($key, $offset = 1) { @@ -97,7 +95,7 @@ class ApcEngine extends CacheEngine { * Delete a key from the cache * * @param string $key Identifier for the data - * @return boolean True if the value was succesfully deleted, false if it didn't exist or couldn't be removed + * @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed */ public function delete($key) { return apc_delete($key); @@ -106,7 +104,7 @@ class ApcEngine extends CacheEngine { /** * Delete all keys from the cache. This will clear every cache config using APC. * - * @return boolean True if the cache was succesfully cleared, false otherwise + * @return boolean True if the cache was successfully cleared, false otherwise */ public function clear($check) { return apc_clear_cache('user'); diff --git a/lib/Cake/Cache/Engine/FileEngine.php b/lib/Cake/Cache/Engine/FileEngine.php index fd6286b9a..531ca928f 100644 --- a/lib/Cake/Cache/Engine/FileEngine.php +++ b/lib/Cake/Cache/Engine/FileEngine.php @@ -63,7 +63,7 @@ class FileEngine extends CacheEngine { * Called automatically by the cache frontend * To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array()); * - * @param array $setting array of setting for the engine + * @param array $settings array of setting for the engine * @return boolean True if the engine has been successfully initialized, false if not */ public function init($settings = array()) { @@ -99,7 +99,7 @@ class FileEngine extends CacheEngine { * @param string $key Identifier for the data * @param mixed $data Data to be cached * @param mixed $duration How long to cache the data, in seconds - * @return boolean True if the data was succesfully cached, false on failure + * @return boolean True if the data was successfully cached, false on failure */ public function write($key, $data, $duration) { if ($data === '' || !$this->_init) { @@ -204,7 +204,7 @@ class FileEngine extends CacheEngine { * Delete all values from the cache * * @param boolean $check Optional - only delete expired cache items - * @return boolean True if the cache was succesfully cleared, false otherwise + * @return boolean True if the cache was successfully cleared, false otherwise */ public function clear($check) { if (!$this->_init) { diff --git a/lib/Cake/Cache/Engine/MemcacheEngine.php b/lib/Cake/Cache/Engine/MemcacheEngine.php index 7b9aa5523..34ee10043 100644 --- a/lib/Cake/Cache/Engine/MemcacheEngine.php +++ b/lib/Cake/Cache/Engine/MemcacheEngine.php @@ -53,7 +53,7 @@ class MemcacheEngine extends CacheEngine { * Called automatically by the cache frontend * To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array()); * - * @param array $setting array of setting for the engine + * @param array $settings array of setting for the engine * @return boolean True if the engine has been successfully initialized, false if not */ public function init($settings = array()) { @@ -121,7 +121,7 @@ class MemcacheEngine extends CacheEngine { * @param string $key Identifier for the data * @param mixed $value Data to be cached * @param integer $duration How long to cache the data, in seconds - * @return boolean True if the data was succesfully cached, false on failure + * @return boolean True if the data was successfully cached, false on failure * @see http://php.net/manual/en/memcache.set.php */ public function write($key, $value, $duration) { @@ -146,7 +146,6 @@ class MemcacheEngine extends CacheEngine { * * @param string $key Identifier for the data * @param integer $offset How much to increment - * @param integer $duration How long to cache the data, in seconds * @return New incremented value, false otherwise * @throws CacheException when you try to increment with compress = true */ @@ -163,8 +162,7 @@ class MemcacheEngine extends CacheEngine { * Decrements the value of an integer cached key * * @param string $key Identifier for the data - * @param integer $offset How much to substract - * @param integer $duration How long to cache the data, in seconds + * @param integer $offset How much to subtract * @return New decremented value, false otherwise * @throws CacheException when you try to decrement with compress = true */ @@ -181,7 +179,7 @@ class MemcacheEngine extends CacheEngine { * Delete a key from the cache * * @param string $key Identifier for the data - * @return boolean True if the value was succesfully deleted, false if it didn't exist or couldn't be removed + * @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed */ public function delete($key) { return $this->_Memcache->delete($key); @@ -190,7 +188,7 @@ class MemcacheEngine extends CacheEngine { /** * Delete all keys from the cache * - * @return boolean True if the cache was succesfully cleared, false otherwise + * @return boolean True if the cache was successfully cleared, false otherwise */ public function clear($check) { return $this->_Memcache->flush(); diff --git a/lib/Cake/Cache/Engine/XcacheEngine.php b/lib/Cake/Cache/Engine/XcacheEngine.php index 53b0d08b9..cc169403c 100644 --- a/lib/Cake/Cache/Engine/XcacheEngine.php +++ b/lib/Cake/Cache/Engine/XcacheEngine.php @@ -42,7 +42,7 @@ class XcacheEngine extends CacheEngine { * Called automatically by the cache frontend * To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array()); * - * @param array $setting array of setting for the engine + * @param array $settings array of setting for the engine * @return boolean True if the engine has been successfully initialized, false if not */ public function init($settings) { @@ -62,7 +62,7 @@ class XcacheEngine extends CacheEngine { * @param string $key Identifier for the data * @param mixed $value Data to be cached * @param integer $duration How long to cache the data, in seconds - * @return boolean True if the data was succesfully cached, false on failure + * @return boolean True if the data was successfully cached, false on failure */ public function write($key, $value, $duration) { $expires = time() + $duration; @@ -94,7 +94,6 @@ class XcacheEngine extends CacheEngine { * * @param string $key Identifier for the data * @param integer $offset How much to increment - * @param integer $duration How long to cache the data, in seconds * @return New incremented value, false otherwise */ public function increment($key, $offset = 1) { @@ -106,8 +105,7 @@ class XcacheEngine extends CacheEngine { * If the cache key is not an integer it will be treated as 0 * * @param string $key Identifier for the data - * @param integer $offset How much to substract - * @param integer $duration How long to cache the data, in seconds + * @param integer $offset How much to subtract * @return New decremented value, false otherwise */ public function decrement($key, $offset = 1) { @@ -117,7 +115,7 @@ class XcacheEngine extends CacheEngine { * Delete a key from the cache * * @param string $key Identifier for the data - * @return boolean True if the value was succesfully deleted, false if it didn't exist or couldn't be removed + * @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed */ public function delete($key) { return xcache_unset($key); @@ -126,7 +124,7 @@ class XcacheEngine extends CacheEngine { /** * Delete all keys from the cache * - * @return boolean True if the cache was succesfully cleared, false otherwise + * @return boolean True if the cache was successfully cleared, false otherwise */ public function clear($check) { $this->__auth(); @@ -145,7 +143,7 @@ class XcacheEngine extends CacheEngine { * This has to be done because xcache_clear_cache() needs to pass Basic Http Auth * (see xcache.admin configuration settings) * - * @param boolean Revert changes + * @param boolean $reverse Revert changes * @access private */ function __auth($reverse = false) { diff --git a/lib/Cake/Console/Command/SchemaShell.php b/lib/Cake/Console/Command/SchemaShell.php index f3faa5890..e051355c9 100644 --- a/lib/Cake/Console/Command/SchemaShell.php +++ b/lib/Cake/Console/Command/SchemaShell.php @@ -20,6 +20,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ App::uses('File', 'Utility'); +App::uses('Folder', 'Utility'); App::uses('CakeSchema', 'Model'); /** @@ -60,7 +61,7 @@ class SchemaShell extends Shell { * */ public function startup() { - $name = $file = $path = $connection = $plugin = null; + $name = $path = $connection = $plugin = null; if (!empty($this->params['name'])) { $name = $this->params['name']; } elseif (!empty($this->args[0])) { @@ -150,7 +151,7 @@ class SchemaShell extends Shell { $content = $this->Schema->read($options); $content['file'] = $this->params['file']; - + Configure::write('Cache.disable', $cacheDisable); if ($snapshot === true) { @@ -271,7 +272,7 @@ class SchemaShell extends Shell { if (!empty($this->params['plugin'])) { $plugin = $this->params['plugin']; } - + if (!empty($this->params['dry'])) { $this->__dry = true; $this->out(__d('cake_console', 'Performing a dry run.')); @@ -463,7 +464,7 @@ class SchemaShell extends Shell { $write = array( 'help' => __d('cake_console', 'Write the dumped SQL to a file.') ); - + $parser = parent::getOptionParser(); $parser->description( 'The Schema Shell generates a schema object from' . diff --git a/lib/Cake/Console/Command/Task/ExtractTask.php b/lib/Cake/Console/Command/Task/ExtractTask.php index 8e20fabe2..bcf38d386 100644 --- a/lib/Cake/Console/Command/Task/ExtractTask.php +++ b/lib/Cake/Console/Command/Task/ExtractTask.php @@ -17,6 +17,8 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ App::uses('File', 'Utility'); +App::uses('Folder', 'Utility'); + /** * Language string extractor * @@ -112,7 +114,7 @@ class ExtractTask extends Shell { $this->__paths = explode(',', $this->params['paths']); } else { $defaultPath = APP_PATH; - $message = __d('cake_console', "What is the full path you would like to extract?\nExample: %s\n[Q]uit [D]one", $defaultPath); + $message = __d('cake_console', "What is the path you would like to extract?\n[Q]uit [D]one"); while (true) { $response = $this->in($message, null, $defaultPath); if (strtoupper($response) === 'Q') { @@ -134,7 +136,7 @@ class ExtractTask extends Shell { if (isset($this->params['output'])) { $this->__output = $this->params['output']; } else { - $message = __d('cake_console', "What is the full path you would like to output?\nExample: %s\n[Q]uit", $this->__paths[0] . DS . 'locale'); + $message = __d('cake_console', "What is the path you would like to output?\n[Q]uit", $this->__paths[0] . DS . 'locale'); while (true) { $response = $this->in($message, null, $this->__paths[0] . DS . 'locale'); if (strtoupper($response) === 'Q') { @@ -199,13 +201,13 @@ class ExtractTask extends Shell { $parser = parent::getOptionParser(); return $parser->description(__d('cake_console', 'CakePHP Language String Extraction:')) ->addOption('app', array('help' => __d('cake_console', 'Directory where your application is located.'))) - ->addOption('paths', array('help' => __d('cake_console', 'Comma separted list of paths, full paths are needed.'))) + ->addOption('paths', array('help' => __d('cake_console', 'Comma separted list of paths.'))) ->addOption('merge', array( 'help' => __d('cake_console', 'Merge all domain strings into the default.po file.'), 'choices' => array('yes', 'no') )) ->addOption('output', array('help' => __d('cake_console', 'Full path to output directory.'))) - ->addOption('files', array('help' => __d('cake_console', 'Comma separated list of files, full paths are needed.'))) + ->addOption('files', array('help' => __d('cake_console', 'Comma separated list of files.'))) ->addOption('exclude', array( 'help' => __d('cake_console', 'Comma separated list of directories to exclude. Any path containing a path segment with the provided values will be skipped. E.g. test,vendors') )); @@ -229,10 +231,10 @@ class ExtractTask extends Shell { $this->out(__d('cake_console', ' -app [path...]: directory where your application is located')); $this->out(__d('cake_console', ' -root [path...]: path to install')); $this->out(__d('cake_console', ' -core [path...]: path to cake directory')); - $this->out(__d('cake_console', ' -paths [comma separated list of paths, full path is needed]')); + $this->out(__d('cake_console', ' -paths [comma separated list of paths]')); $this->out(__d('cake_console', ' -merge [yes|no]: Merge all domains strings into the default.pot file')); $this->out(__d('cake_console', ' -output [path...]: Full path to output directory')); - $this->out(__d('cake_console', ' -files: [comma separated list of files, full path to file is needed]')); + $this->out(__d('cake_console', ' -files: [comma separated list of files]')); $this->out(); $this->out(__d('cake_console', 'Commands:')); $this->out(__d('cake_console', ' cake i18n extract help: Shows this help message.')); @@ -415,7 +417,7 @@ class ExtractTask extends Shell { if (strtoupper($response) === 'N') { $response = ''; while ($response == '') { - $response = $this->in(__d('cake_console', "What would you like to name this file?\nExample: %s", 'new_' . $filename), null, 'new_' . $filename); + $response = $this->in(__d('cake_console', "What would you like to name this file?"), null, 'new_' . $filename); $File = new File($this->__output . $response); $filename = $response; } @@ -515,7 +517,7 @@ class ExtractTask extends Shell { function __searchFiles() { $pattern = false; if (!empty($this->_exclude)) { - $pattern = '/[\/\\\\]' . implode('|', $this->_exclude) . '[\/\\\\]/'; + $pattern = '/[\/\\\\]' . implode('|', $this->_exclude) . '[\/\\\\]/'; } foreach ($this->__paths as $path) { $Folder = new Folder($path); diff --git a/lib/Cake/Console/Command/Task/FixtureTask.php b/lib/Cake/Console/Command/Task/FixtureTask.php index daf3e412d..3af4120e4 100644 --- a/lib/Cake/Console/Command/Task/FixtureTask.php +++ b/lib/Cake/Console/Command/Task/FixtureTask.php @@ -140,7 +140,6 @@ class FixtureTask extends BakeTask { $this->out(sprintf("Bake Fixture\nPath: %s", $this->path)); $this->hr(); - $useDbConfig = $this->connection; if (!isset($this->connection)) { $this->connection = $this->DbConfig->getConfig(); } diff --git a/lib/Cake/Console/Command/Task/ModelTask.php b/lib/Cake/Console/Command/Task/ModelTask.php index 1c63147fb..a8aa79e68 100644 --- a/lib/Cake/Console/Command/Task/ModelTask.php +++ b/lib/Cake/Console/Command/Task/ModelTask.php @@ -462,7 +462,6 @@ class ModelTask extends BakeTask { $associations = array( 'belongsTo' => array(), 'hasMany' => array(), 'hasOne'=> array(), 'hasAndBelongsToMany' => array() ); - $possibleKeys = array(); $associations = $this->findBelongsTo($model, $associations); $associations = $this->findHasOneAndMany($model, $associations); @@ -608,8 +607,6 @@ class ModelTask extends BakeTask { public function confirmAssociations($model, $associations) { foreach ($associations as $type => $settings) { if (!empty($associations[$type])) { - $count = count($associations[$type]); - $response = 'y'; foreach ($associations[$type] as $i => $assoc) { $prompt = "{$model->name} {$type} {$assoc['alias']}?"; $response = $this->in($prompt, array('y','n'), 'y'); @@ -647,7 +644,6 @@ class ModelTask extends BakeTask { $alias = $this->in(__d('cake_console', 'What is the alias for this association?')); $className = $this->in(__d('cake_console', 'What className will %s use?', $alias), null, $alias ); - $suggestedForeignKey = null; if ($assocType == 0) { $showKeys = $possibleKeys[$model->table]; diff --git a/lib/Cake/Console/Command/Task/PluginTask.php b/lib/Cake/Console/Command/Task/PluginTask.php index 1b6033137..8c7f2ed50 100644 --- a/lib/Cake/Console/Command/Task/PluginTask.php +++ b/lib/Cake/Console/Command/Task/PluginTask.php @@ -50,8 +50,6 @@ class PluginTask extends Shell { * @return void */ public function execute() { - $plugin = null; - if (isset($this->args[0])) { $plugin = Inflector::camelize($this->args[0]); $pluginPath = $this->_pluginPath($plugin); @@ -107,19 +105,16 @@ class PluginTask extends Shell { $Folder = new Folder($this->path . $pluginPath); $directories = array( 'config' . DS . 'schema', - 'models' . DS . 'behaviors', - 'models' . DS . 'datasources', - 'console' . DS . 'shells' . DS . 'tasks', - 'controllers' . DS . 'components', - 'libs', - 'views' . DS . 'helpers', - 'tests' . DS . 'cases' . DS . 'components', - 'tests' . DS . 'cases' . DS . 'helpers', - 'tests' . DS . 'cases' . DS . 'behaviors', - 'tests' . DS . 'cases' . DS . 'controllers', - 'tests' . DS . 'cases' . DS . 'models', - 'tests' . DS . 'groups', - 'tests' . DS . 'fixtures', + 'Model' . DS . 'Behavior', + 'Model' . DS . 'Datasource', + 'Console' . DS . 'Command' . DS . 'Task', + 'Controller' . DS . 'Component', + 'Lib', + 'View' . DS . 'Helper', + 'tests' . DS . 'Case' . DS . 'Controller' . DS . 'Component', + 'tests' . DS . 'Case' . DS . 'View' . DS . 'Helper', + 'tests' . DS . 'Case' . DS . 'Model' . DS . 'Behavior', + 'tests' . DS . 'Fixture', 'vendors', 'webroot' ); @@ -139,21 +134,21 @@ class PluginTask extends Shell { return false; } - $controllerFileName = $pluginPath . '_app_controller.php'; + $controllerFileName = $plugin . 'AppController.php'; $out = ""; - $this->createFile($this->path . $pluginPath. DS . $controllerFileName, $out); + $this->createFile($this->path . $pluginPath. DS . 'Controller' . DS . $controllerFileName, $out); - $modelFileName = $pluginPath . '_app_model.php'; + $modelFileName = $plugin . 'AppModel.php'; $out = ""; - $this->createFile($this->path . $pluginPath . DS . $modelFileName, $out); + $this->createFile($this->path . $pluginPath . DS . 'Model' . DS . $modelFileName, $out); $this->hr(); $this->out(__d('cake_console', 'Created: %s in %s', $plugin, $this->path . $pluginPath), 2); diff --git a/lib/Cake/Console/Command/Task/ProjectTask.php b/lib/Cake/Console/Command/Task/ProjectTask.php index 368512741..28e06b853 100644 --- a/lib/Cake/Console/Command/Task/ProjectTask.php +++ b/lib/Cake/Console/Command/Task/ProjectTask.php @@ -19,6 +19,7 @@ */ App::uses('File', 'Utility'); +App::uses('Folder', 'Utility'); App::uses('String', 'Utility'); App::uses('Security', 'Utility'); @@ -53,9 +54,8 @@ class ProjectTask extends Shell { } while (!$project) { - $prompt = __d('cake_console', "What is the full path for this app including the app directory name?\n Example:"); - $default = APP_PATH . 'myapp'; - $project = $this->in($prompt . $default, null, $default); + $prompt = __d('cake_console', "What is the path to the project you want to bake?"); + $project = $this->in($prompt, null, APP_PATH . 'myapp'); } if ($project) { @@ -201,7 +201,7 @@ class ProjectTask extends Shell { */ public function createHome($dir) { $app = basename($dir); - $path = $dir . 'views' . DS . 'pages' . DS; + $path = $dir . 'View' . DS . 'pages' . DS; $source = LIBS . 'Console' . DS . 'templates' . DS .'default' . DS . 'views' . DS . 'home.ctp'; include($source); return $this->createFile($path.'home.ctp', $output); @@ -392,4 +392,4 @@ class ProjectTask extends Shell { )); } -} \ No newline at end of file +} diff --git a/lib/Cake/Console/Command/Task/TemplateTask.php b/lib/Cake/Console/Command/Task/TemplateTask.php index 189cf7f83..39c7f8548 100644 --- a/lib/Cake/Console/Command/Task/TemplateTask.php +++ b/lib/Cake/Console/Command/Task/TemplateTask.php @@ -106,7 +106,6 @@ class TemplateTask extends Shell { * @return void */ public function set($one, $two = null) { - $data = null; if (is_array($one)) { if (is_array($two)) { $data = array_combine($one, $two); diff --git a/lib/Cake/Console/Command/Task/TestTask.php b/lib/Cake/Console/Command/Task/TestTask.php index 56ecd502e..014988c56 100644 --- a/lib/Cake/Console/Command/Task/TestTask.php +++ b/lib/Cake/Console/Command/Task/TestTask.php @@ -220,7 +220,7 @@ class TestTask extends BakeTask { /** * Checks whether the chosen type can find its own fixtures. * Currently only model, and controller are supported - * + * * @param string $type The Type of object you are generating tests for eg. controller * @param string $className the Classname of the class the test is being generated for. * @return boolean diff --git a/lib/Cake/Console/Command/Task/ViewTask.php b/lib/Cake/Console/Command/Task/ViewTask.php index 5e9a78c50..03f6c4f3f 100644 --- a/lib/Cake/Console/Command/Task/ViewTask.php +++ b/lib/Cake/Console/Command/Task/ViewTask.php @@ -106,7 +106,7 @@ class ViewTask extends BakeTask { if (!isset($this->connection)) { $this->connection = 'default'; } - $controller = $action = $alias = null; + $action = null; $this->controllerName = $this->_controllerName($this->args[0]); $this->controllerPath = $this->_controllerPath($this->controllerName); diff --git a/lib/Cake/Console/Command/TestsuiteShell.php b/lib/Cake/Console/Command/TestsuiteShell.php index d0d778484..07d9cf4c9 100644 --- a/lib/Cake/Console/Command/TestsuiteShell.php +++ b/lib/Cake/Console/Command/TestsuiteShell.php @@ -163,7 +163,10 @@ class TestsuiteShell extends Shell { */ public function initialize() { $this->_dispatcher = new CakeTestSuiteDispatcher(); - $this->_dispatcher->loadTestFramework(); + $sucess = $this->_dispatcher->loadTestFramework(); + if (!$sucess) { + throw new Exception(__d('cake_dev', 'Please install PHPUnit framework (http://www.phpunit.de)')); + } } /** @@ -289,9 +292,7 @@ class TestsuiteShell extends Shell { $i = 1; $cases = array(); foreach ($testCases as $testCaseFile => $testCase) { - $case = explode(DS, str_replace('Test.php', '', $testCase)); - $case[count($case) - 1] = $case[count($case) - 1]; - $case = implode('/', $case); + $case = str_replace('Test.php', '', $testCase); $this->out("[$i] $case"); $cases[$i] = $case; $i++; diff --git a/lib/Cake/Console/Shell.php b/lib/Cake/Console/Shell.php index ad5b716fa..9ea899bb4 100644 --- a/lib/Cake/Console/Shell.php +++ b/lib/Cake/Console/Shell.php @@ -165,7 +165,7 @@ class Shell extends Object { if ($this->stdin == null) { $this->stdin = new ConsoleInput('php://stdin'); } - + $parent = get_parent_class($this); if ($this->tasks !== null && $this->tasks !== false) { $this->_mergeVars(array('tasks'), $parent, true); @@ -200,7 +200,6 @@ class Shell extends Object { * */ protected function _welcome() { - $this->clear(); $this->out(); $this->out('Welcome to CakePHP v' . Configure::version() . ' Console'); $this->hr(); @@ -296,16 +295,16 @@ class Shell extends Object { * but intended for running shells from other shells. * * ### Usage: - * + * * With a string commmand: * * `return $this->dispatchShell('schema create DbAcl');` * * With an array command: * - * `return $this->dispatchShell('schema', 'create', 'i18n', '--dry');` + * `return $this->dispatchShell('schema', 'create', 'i18n', '--dry');` * - * @param mixed $command Either an array of args similar to $argv. Or a string command, that can be + * @param mixed $command Either an array of args similar to $argv. Or a string command, that can be * exploded on space to simulate argv. * @return mixed. The return of the other shell. */ @@ -334,10 +333,14 @@ class Shell extends Object { array_shift($argv); } - $this->OptionParser = $this->getOptionParser(); - list($this->params, $this->args) = $this->OptionParser->parse($argv, $command); + try { + $this->OptionParser = $this->getOptionParser(); + list($this->params, $this->args) = $this->OptionParser->parse($argv, $command); + } catch (ConsoleException $e) { + return $this->out($this->OptionParser->help($command)); + } + $this->command = $command; - if (!empty($this->params['help'])) { return $this->_displayHelp($command); } @@ -471,7 +474,7 @@ class Shell extends Object { /** * Wrap a block of text. - * Allows you to set the width, and indenting on a block of text. + * Allows you to set the width, and indenting on a block of text. * * ### Options * @@ -480,7 +483,7 @@ class Shell extends Object { * - `indent` Indent the text with the string provided. Defaults to null. * * @param string $text Text the text to format. - * @param mixed $options Array of options to use, or an integer to wrap the text to. + * @param mixed $options Array of options to use, or an integer to wrap the text to. * @return string Wrapped / indented text * @see String::wrap() */ diff --git a/lib/Cake/Console/TaskCollection.php b/lib/Cake/Console/TaskCollection.php index 3c911a2ce..a3f56082c 100644 --- a/lib/Cake/Console/TaskCollection.php +++ b/lib/Cake/Console/TaskCollection.php @@ -58,7 +58,6 @@ class TaskCollection extends ObjectCollection { if (isset($this->_loaded[$name])) { return $this->_loaded[$name]; } - $taskFile = Inflector::underscore($name); $taskClass = $name . 'Task'; App::uses($taskClass, $plugin . 'Console/Command/Task'); if (!class_exists($taskClass)) { diff --git a/lib/Cake/Console/templates/skel/Console/cake.php b/lib/Cake/Console/templates/skel/Console/cake.php index d4f4ef1c0..7f3387dc6 100644 --- a/lib/Cake/Console/templates/skel/Console/cake.php +++ b/lib/Cake/Console/templates/skel/Console/cake.php @@ -19,6 +19,6 @@ * @since CakePHP(tm) v 1.2.0.5012 * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ -require_once(__CAKE_PATH__ . 'shell_dispatcher.php'); +require_once(__CAKE_PATH__ . 'ShellDispatcher.php'); return ShellDispatcher::run($argv); diff --git a/lib/Cake/Console/templates/skel/View/elements/email/html/default.ctp b/lib/Cake/Console/templates/skel/View/emails/html/default.ctp similarity index 100% rename from lib/Cake/Console/templates/skel/View/elements/email/html/default.ctp rename to lib/Cake/Console/templates/skel/View/emails/html/default.ctp diff --git a/lib/Cake/Console/templates/skel/View/elements/email/text/default.ctp b/lib/Cake/Console/templates/skel/View/emails/text/default.ctp similarity index 100% rename from lib/Cake/Console/templates/skel/View/elements/email/text/default.ctp rename to lib/Cake/Console/templates/skel/View/emails/text/default.ctp diff --git a/lib/Cake/Console/templates/skel/View/layouts/email/html/default.ctp b/lib/Cake/Console/templates/skel/View/layouts/emails/html/default.ctp similarity index 100% rename from lib/Cake/Console/templates/skel/View/layouts/email/html/default.ctp rename to lib/Cake/Console/templates/skel/View/layouts/emails/html/default.ctp diff --git a/lib/Cake/Console/templates/skel/View/layouts/email/text/default.ctp b/lib/Cake/Console/templates/skel/View/layouts/emails/text/default.ctp similarity index 100% rename from lib/Cake/Console/templates/skel/View/layouts/email/text/default.ctp rename to lib/Cake/Console/templates/skel/View/layouts/emails/text/default.ctp diff --git a/lib/Cake/Console/templates/skel/config/core.php b/lib/Cake/Console/templates/skel/config/core.php index 3a7613b85..c445896b1 100644 --- a/lib/Cake/Console/templates/skel/config/core.php +++ b/lib/Cake/Console/templates/skel/config/core.php @@ -41,7 +41,7 @@ * * Options: * - * - `handler` - callback - The callback to handle errors. You can set this to any callback type, + * - `handler` - callback - The callback to handle errors. You can set this to any callback type, * including anonymous functions. * - `level` - int - The level of errors you are interested in capturing. * - `trace` - boolean - Include stack traces for errors in log files. @@ -55,14 +55,14 @@ )); /** - * Configure the Exception handler used for uncaught exceptions. By default, - * ErrorHandler::handleException() is used. It will display a HTML page for the exception, and - * while debug > 0, framework errors like Missing Controller will be displayed. When debug = 0, + * Configure the Exception handler used for uncaught exceptions. By default, + * ErrorHandler::handleException() is used. It will display a HTML page for the exception, and + * while debug > 0, framework errors like Missing Controller will be displayed. When debug = 0, * framework errors will be coerced into generic HTTP errors. * * Options: * - * - `handler` - callback - The callback to handle exceptions. You can set this to any callback type, + * - `handler` - callback - The callback to handle exceptions. You can set this to any callback type, * including anonymous functions. * - `renderer` - string - The class responsible for rendering uncaught exceptions. If you choose a custom class you * should place the file for that class in app/libs. This class needs to implement a render method. @@ -138,7 +138,7 @@ /** * Session configuration. * - * Contains an array of settings to use for session configuration. The defaults key is + * Contains an array of settings to use for session configuration. The defaults key is * used to define a default preset to use for sessions, any settings declared here will override * the settings of the default config. * @@ -147,14 +147,14 @@ * - `Session.name` - The name of the cookie to use. Defaults to 'CAKEPHP' * - `Session.timeout` - The number of minutes you want sessions to live for. This timeout is handled by CakePHP * - `Session.cookieTimeout` - The number of minutes you want session cookies to live for. - * - `Session.checkAgent` - Do you want the user agent to be checked when starting sessions? You might want to set the + * - `Session.checkAgent` - Do you want the user agent to be checked when starting sessions? You might want to set the * value to false, when dealing with older versions of IE, Chrome Frame or certain web-browsing devices and AJAX * - `Session.defaults` - The default configuration set to use as a basis for your session. * There are four builtins: php, cake, cache, database. * - `Session.handler` - Can be used to enable a custom session handler. Expects an array of of callables, * that can be used with `session_save_handler`. Using this option will automatically add `session.save_handler` * to the ini array. - * - `Session.autoRegenerate` - Enabling this setting, turns on automatic renewal of sessions, and + * - `Session.autoRegenerate` - Enabling this setting, turns on automatic renewal of sessions, and * sessionids that change frequently. See CakeSession::$requestCountdown. * - `Session.ini` - An associative array of additional ini values to set. * @@ -284,9 +284,13 @@ * */ -// Pick the caching engine to use. If APC is enabled use it. +/** + * Pick the caching engine to use. If APC is enabled use it. + * If running via cli - apc is disabled by default. ensure it's avaiable and enabled in this case + * + */ $engine = 'File'; -if (extension_loaded('apc')) { +if (extension_loaded('apc') && (php_sapi_name() !== 'cli' || ini_get('apc.enable_cli'))) { $engine = 'Apc'; } @@ -309,7 +313,7 @@ Cache::config('_cake_core_', array( )); /** - * Configure the cache for model, and datasource caches. This cache configuration + * Configure the cache for model, and datasource caches. This cache configuration * is used to store schema descriptions, and table listings in connections. */ Cache::config('_cake_model_', array( diff --git a/lib/Cake/Console/templates/skel/config/email.php.default b/lib/Cake/Console/templates/skel/config/email.php.default new file mode 100644 index 000000000..66c378f35 --- /dev/null +++ b/lib/Cake/Console/templates/skel/config/email.php.default @@ -0,0 +1,88 @@ + The name of a supported transport; valid options are as follows: + * mail - Send using PHP mail function + * smtp - Send using SMTP + * + * You can add custom transports (or override existing transports) by adding the + * appropriate file to app/Network/Email. Transports should be named 'YourTransport.php', + * where 'Your' is the name of the transport. + * + * from => + * The origin email. See CakeEmail::from() about the valid values + * + */ +class EmailConfig { + + public $default = array( + 'transport' => 'mail', + 'from' => 'you@localhost' + ); + + public $smtp = array( + 'transport' => 'smtp', + 'from' => array('My Site', 'site@localhost'), + 'host' => 'localhost', + 'port' => 25, + 'timeout' => 30, + 'username' => 'user', + 'password' => 'secret', + 'client' => null + ); + + public $fast = array( + 'from' => 'you@localhost', + 'sender' => null, + 'to' => null, + 'cc' => null, + 'bcc' => null, + 'replyTo' => null, + 'readReceipt' => null, + 'returnPath' => null, + 'messageId' => true, + 'subject' => null, + 'message' => null, + 'headers' => null, + 'viewRender' => null, + 'template' => false, + 'layout' => false, + 'viewVars' => null, + 'attachments' => null, + 'emailFormat' => null, + 'transport' => 'smtp', + 'host' => 'localhost', + 'port' => 25, + 'timeout' => 30, + 'username' => 'user', + 'password' => 'secret', + 'client' => null + ); + +} diff --git a/lib/Cake/Console/templates/skel/webroot/css.php b/lib/Cake/Console/templates/skel/webroot/css.php deleted file mode 100644 index 59505c4e9..000000000 --- a/lib/Cake/Console/templates/skel/webroot/css.php +++ /dev/null @@ -1,96 +0,0 @@ -compress($data); - $ratio = 100 - (round(strlen($output) / strlen($data), 3) * 100); - $output = " /* file: $name, ratio: $ratio% */ " . $output; - return $output; - } - -/** - * Write CSS cache - * - * @param unknown_type $path - * @param unknown_type $content - * @return unknown - */ - function write_css_cache($path, $content) { - if (!is_dir(dirname($path))) { - mkdir(dirname($path)); - } - $cache = new File($path); - return $cache->write($content); - } - - if (preg_match('|\.\.|', $url) || !preg_match('|^ccss/(.+)$|i', $url, $regs)) { - exit('Wrong file name.'); - } - - $filename = 'css/' . $regs[1]; - $filepath = CSS . $regs[1]; - $cachepath = CACHE . 'css' . DS . str_replace(array('/','\\'), '-', $regs[1]); - - if (!file_exists($filepath)) { - exit('Wrong file name.'); - } - - if (file_exists($cachepath)) { - $templateModified = filemtime($filepath); - $cacheModified = filemtime($cachepath); - - if ($templateModified > $cacheModified) { - $output = make_clean_css($filepath, $filename); - write_css_cache($cachepath, $output); - } else { - $output = file_get_contents($cachepath); - } - } else { - $output = make_clean_css($filepath, $filename); - write_css_cache($cachepath, $output); - $templateModified = time(); - } - - header("Date: " . date("D, j M Y G:i:s ", $templateModified) . 'GMT'); - header("Content-Type: text/css"); - header("Expires: " . gmdate("D, j M Y H:i:s", time() + DAY) . " GMT"); - header("Cache-Control: max-age=86400, must-revalidate"); // HTTP/1.1 - header("Pragma: cache"); // HTTP/1.0 - print $output; diff --git a/lib/Cake/Console/templates/skel/webroot/index.php b/lib/Cake/Console/templates/skel/webroot/index.php index 77b9db786..3c5e71589 100644 --- a/lib/Cake/Console/templates/skel/webroot/index.php +++ b/lib/Cake/Console/templates/skel/webroot/index.php @@ -75,6 +75,6 @@ return; } - require LIBS . 'Routing' . DS .'Dispatcher.php'; + App::uses('Dispatcher', 'Routing'); $Dispatcher = new Dispatcher(); $Dispatcher->dispatch(new CakeRequest()); diff --git a/lib/Cake/Controller/Component/AclComponent.php b/lib/Cake/Controller/Component/AclComponent.php index fde44da62..5d2348e52 100644 --- a/lib/Cake/Controller/Component/AclComponent.php +++ b/lib/Cake/Controller/Component/AclComponent.php @@ -308,9 +308,6 @@ class DbAcl extends Object implements AclInterface { return false; } - $aroNode = $aroPath[0]; - $acoNode = $acoPath[0]; - if ($action != '*' && !in_array('_' . $action, $permKeys)) { trigger_error(__d('cake_dev', "ACO permissions key %s does not exist in DbAcl::check()", $action), E_USER_NOTICE); return false; diff --git a/lib/Cake/Controller/Component/CookieComponent.php b/lib/Cake/Controller/Component/CookieComponent.php index cca49a5bf..83e6353ca 100644 --- a/lib/Cake/Controller/Component/CookieComponent.php +++ b/lib/Cake/Controller/Component/CookieComponent.php @@ -459,23 +459,24 @@ class CookieComponent extends Component { * Implode method to keep keys are multidimensional arrays * * @param array $array Map of key and values - * @return string String in the form key1|value1,key2|value2 + * @return string A json encoded string. */ - protected function _implode($array) { - $string = ''; - foreach ($array as $key => $value) { - $string .= ',' . $key . '|' . $value; - } - return substr($string, 1); + protected function _implode(array $array) { + return json_encode($array); } /** * Explode method to return array from string set in CookieComponent::_implode() + * Maintains reading backwards compatibility with 1.x CookieComponent::_implode(). * - * @param string $string String in the form key1|value1,key2|value2 + * @param string $string A string containing JSON encoded data, or a bare string. * @return array Map of key and values */ protected function _explode($string) { + if ($string[0] === '{' || $string[0] === '[') { + $ret = json_decode($string, true); + return ($ret != null) ? $ret : $string; + } $array = array(); foreach (explode(',', $string) as $pair) { $key = explode('|', $pair); diff --git a/lib/Cake/Controller/Component/EmailComponent.php b/lib/Cake/Controller/Component/EmailComponent.php index 103ccafed..2311f0d55 100644 --- a/lib/Cake/Controller/Component/EmailComponent.php +++ b/lib/Cake/Controller/Component/EmailComponent.php @@ -19,6 +19,7 @@ App::uses('Component', 'Controller'); App::uses('Multibyte', 'I18n'); +App::uses('CakeEmail', 'Network'); /** * EmailComponent @@ -28,7 +29,7 @@ App::uses('Multibyte', 'I18n'); * * @package cake.libs.controller.components * @link http://book.cakephp.org/view/1283/Email - * + * @deprecated Use Network/CakeEmail */ class EmailComponent extends Component { @@ -149,14 +150,6 @@ class EmailComponent extends Component { */ public $template = null; -/** - * as per RFC2822 Section 2.1.1 - * - * @var integer - * @access public - */ - public $lineLength = 70; - /** * Line feed character(s) to be used when sending using mail() function * By default PHP_EOL is used. @@ -167,12 +160,7 @@ class EmailComponent extends Component { * @var string * @access public */ - var $lineFeed = PHP_EOL; - -/** - * @deprecated see lineLength - */ - protected $_lineLength = null; + public $lineFeed = PHP_EOL; /** * What format should the email be sent in @@ -251,15 +239,6 @@ class EmailComponent extends Component { */ public $smtpOptions = array(); -/** - * Placeholder for any errors that might happen with the - * smtp mail methods - * - * @var string - * @access public - */ - public $smtpError = null; - /** * Contains the rendered plain text message if one was sent. * @@ -291,36 +270,11 @@ class EmailComponent extends Component { public $messageId = true; /** - * Temporary store of message header lines + * Controller reference * - * @var array - * @access protected + * @var object Controller */ - protected $_header = array(); - -/** - * If set, boundary to use for multipart mime messages - * - * @var string - * @access protected - */ - protected $_boundary = null; - -/** - * Temporary store of message lines - * - * @var array - * @access protected - */ - protected $_message = array(); - -/** - * Variable that holds SMTP connection - * - * @var resource - * @access protected - */ - protected $_smtpConnection = null; + protected $_controller = null; /** * Constructor @@ -329,7 +283,7 @@ class EmailComponent extends Component { * @param array $settings Array of configuration settings. */ public function __construct(ComponentCollection $collection, $settings = array()) { - $this->Controller = $collection->getController(); + $this->_controller = $collection->getController(); parent::__construct($collection, $settings); } @@ -344,13 +298,6 @@ class EmailComponent extends Component { } } -/** - * Startup component - * - * @param object $controller Instantiating controller - */ - public function startup($controller) {} - /** * Send an email using the specified content, template and layout * @@ -361,59 +308,71 @@ class EmailComponent extends Component { * @return boolean Success */ public function send($content = null, $template = null, $layout = null) { - $this->_createHeader(); + $lib = new CakeEmail(); + $lib->charset = $this->charset; + + $lib->from($this->_formatAddresses((array)$this->from)); + if (!empty($this->to)) { + $lib->to($this->_formatAddresses((array)$this->to)); + } + if (!empty($this->cc)) { + $lib->cc($this->_formatAddresses((array)$this->cc)); + } + if (!empty($this->bcc)) { + $lib->bcc($this->_formatAddresses((array)$this->bcc)); + } + if (!empty($this->replyTo)) { + $lib->replyTo($this->_formatAddresses((array)$this->replyTo)); + } + if (!empty($this->return)) { + $lib->returnPath($this->_formatAddresses((array)$this->return)); + } + if (!empty($readReceipt)) { + $lib->readReceipt($this->_formatAddresses((array)$this->readReceipt)); + } + + $lib->subject($this->subject)->messageID($this->messageId); + + $headers = array('X-Mailer' => $this->xMailer); + foreach ($this->headers as $key => $value) { + $headers['X-' . $key] = $value; + } + if ($this->date != false) { + $headers['Date'] = $this->date; + } + $lib->setHeaders($headers); if ($template) { $this->template = $template; } - if ($layout) { $this->layout = $layout; } - - if (is_array($content)) { - $content = implode("\n", $content) . "\n"; - } - - $this->htmlMessage = $this->textMessage = null; - if ($content) { - if ($this->sendAs === 'html') { - $this->htmlMessage = $content; - } elseif ($this->sendAs === 'text') { - $this->textMessage = $content; - } else { - $this->htmlMessage = $this->textMessage = $content; - } - } - - if ($this->sendAs === 'text') { - $message = $this->_wrap($content); - } else { - $message = $this->_wrap($content, 998); - } - - if ($this->template === null) { - $message = $this->_formatMessage($message); - } else { - $message = $this->_render($message); - } - - $message[] = ''; - $this->_message = $message; + $lib->template($this->template, $this->layout)->viewVars($this->_controller->viewVars)->emailFormat($this->sendAs); if (!empty($this->attachments)) { - $this->_attachFiles(); + $lib->attachments($this->_formatAttachFiles()); } - if (!is_null($this->_boundary)) { - $this->_message[] = ''; - $this->_message[] = '--' . $this->_boundary . '--'; - $this->_message[] = ''; + $lib->transport($this->delivery); + if ($this->delivery === 'mail') { + $lib->config(array('eol' => $this->lineFeed, 'additionalParameters' => $this->additionalParams)); + } elseif ($this->delivery === 'smtp') { + $lib->config($this->smtpOptions); + } else { + $lib->config(array()); } + $sent = $lib->send($content); - $_method = '_' . $this->delivery; - $sent = $this->$_method(); + $this->htmlMessage = $lib->message(CakeEmail::MESSAGE_HTML); + if (empty($this->htmlMessage)) { + $this->htmlMessage = null; + } + $this->textMessage = $lib->message(CakeEmail::MESSAGE_TEXT); + if (empty($this->textMessage)) { + $this->textMessage = null; + } $this->_header = array(); $this->_message = array(); @@ -437,232 +396,18 @@ class EmailComponent extends Component { $this->subject = null; $this->additionalParams = null; $this->date = null; - $this->smtpError = null; $this->attachments = array(); $this->htmlMessage = null; $this->textMessage = null; $this->messageId = true; - $this->_header = array(); - $this->_boundary = null; - $this->_message = array(); } /** - * Render the contents using the current layout and template. + * Format the attach array * - * @param string $content Content to render - * @return array Email ready to be sent - * @access private + * @return array */ - function _render($content) { - $viewClass = $this->Controller->view; - - if ($viewClass != 'View') { - list($plugin, $viewClass) = pluginSplit($viewClass, true); - $viewClass = $viewClass . 'View'; - App::uses($viewClass, $plugin . 'View'); - } - - $View = new $viewClass($this->Controller); - $View->layout = $this->layout; - $msg = array(); - - $content = implode("\n", $content); - - if ($this->sendAs === 'both') { - $htmlContent = $content; - if (!empty($this->attachments)) { - $msg[] = '--' . $this->_boundary; - $msg[] = 'Content-Type: multipart/alternative; boundary="alt-' . $this->_boundary . '"'; - $msg[] = ''; - } - $msg[] = '--alt-' . $this->_boundary; - $msg[] = 'Content-Type: text/plain; charset=' . $this->charset; - $msg[] = 'Content-Transfer-Encoding: 7bit'; - $msg[] = ''; - - $content = $View->element('email' . DS . 'text' . DS . $this->template, array('content' => $content), true); - $View->layoutPath = 'email' . DS . 'text'; - $content = explode("\n", $this->textMessage = str_replace(array("\r\n", "\r"), "\n", $View->renderLayout($content))); - - $msg = array_merge($msg, $content); - - $msg[] = ''; - $msg[] = '--alt-' . $this->_boundary; - $msg[] = 'Content-Type: text/html; charset=' . $this->charset; - $msg[] = 'Content-Transfer-Encoding: 7bit'; - $msg[] = ''; - - $htmlContent = $View->element('email' . DS . 'html' . DS . $this->template, array('content' => $htmlContent), true); - $View->layoutPath = 'email' . DS . 'html'; - $htmlContent = explode("\n", $this->htmlMessage = str_replace(array("\r\n", "\r"), "\n", $View->renderLayout($htmlContent))); - $msg = array_merge($msg, $htmlContent); - $msg[] = ''; - $msg[] = '--alt-' . $this->_boundary . '--'; - $msg[] = ''; - - ClassRegistry::removeObject('view'); - return $msg; - } - - if (!empty($this->attachments)) { - if ($this->sendAs === 'html') { - $msg[] = ''; - $msg[] = '--' . $this->_boundary; - $msg[] = 'Content-Type: text/html; charset=' . $this->charset; - $msg[] = 'Content-Transfer-Encoding: 7bit'; - $msg[] = ''; - } else { - $msg[] = '--' . $this->_boundary; - $msg[] = 'Content-Type: text/plain; charset=' . $this->charset; - $msg[] = 'Content-Transfer-Encoding: 7bit'; - $msg[] = ''; - } - } - - $content = $View->element('email' . DS . $this->sendAs . DS . $this->template, array('content' => $content), true); - $View->layoutPath = 'email' . DS . $this->sendAs; - $content = explode("\n", $rendered = str_replace(array("\r\n", "\r"), "\n", $View->renderLayout($content))); - - if ($this->sendAs === 'html') { - $this->htmlMessage = $rendered; - } else { - $this->textMessage = $rendered; - } - - $msg = array_merge($msg, $content); - ClassRegistry::removeObject('view'); - - return $msg; - } - -/** - * Create unique boundary identifier - * - * @access private - */ - function _createboundary() { - $this->_boundary = md5(uniqid(time())); - } - -/** - * Sets headers for the message - * - * @access public - * @param array Associative array containing headers to be set. - */ - function header($headers) { - foreach ($headers as $header => $value) { - $this->_header[] = sprintf('%s: %s', trim($header), trim($value)); - } - } -/** - * Create emails headers including (but not limited to) from email address, reply to, - * bcc and cc. - * - * @access private - */ - function _createHeader() { - $headers = array(); - - if ($this->delivery == 'smtp') { - $headers['To'] = implode(', ', array_map(array($this, '_formatAddress'), (array)$this->to)); - } - $headers['From'] = $this->_formatAddress($this->from); - - if (!empty($this->replyTo)) { - $headers['Reply-To'] = $this->_formatAddress($this->replyTo); - } - if (!empty($this->return)) { - $headers['Return-Path'] = $this->_formatAddress($this->return); - } - if (!empty($this->readReceipt)) { - $headers['Disposition-Notification-To'] = $this->_formatAddress($this->readReceipt); - } - - if (!empty($this->cc)) { - $headers['Cc'] = implode(', ', array_map(array($this, '_formatAddress'), (array)$this->cc)); - } - - if (!empty($this->bcc) && $this->delivery != 'smtp') { - $headers['Bcc'] = implode(', ', array_map(array($this, '_formatAddress'), (array)$this->bcc)); - } - if ($this->delivery == 'smtp') { - $headers['Subject'] = $this->_encode($this->subject); - } - - if ($this->messageId !== false) { - if ($this->messageId === true) { - $headers['Message-ID'] = '<' . String::UUID() . '@' . env('HTTP_HOST') . '>'; - } else { - $headers['Message-ID'] = $this->messageId; - } - } - - $date = $this->date; - if ($date == false) { - $date = date(DATE_RFC2822); - } - $headers['Date'] = $date; - - $headers['X-Mailer'] = $this->xMailer; - - if (!empty($this->headers)) { - foreach ($this->headers as $key => $val) { - $headers['X-' . $key] = $val; - } - } - - if (!empty($this->attachments)) { - $this->_createBoundary(); - $headers['MIME-Version'] = '1.0'; - $headers['Content-Type'] = 'multipart/mixed; boundary="' . $this->_boundary . '"'; - $headers[] = 'This part of the E-mail should never be seen. If'; - $headers[] = 'you are reading this, consider upgrading your e-mail'; - $headers[] = 'client to a MIME-compatible client.'; - } elseif ($this->sendAs === 'text') { - $headers['Content-Type'] = 'text/plain; charset=' . $this->charset; - } elseif ($this->sendAs === 'html') { - $headers['Content-Type'] = 'text/html; charset=' . $this->charset; - } elseif ($this->sendAs === 'both') { - $headers['Content-Type'] = 'multipart/alternative; boundary="alt-' . $this->_boundary . '"'; - } - - $headers['Content-Transfer-Encoding'] = '7bit'; - - $this->header($headers); - } - -/** - * Format the message by seeing if it has attachments. - * - * @param string $message Message to format - * @access private - */ - function _formatMessage($message) { - if (!empty($this->attachments)) { - $prefix = array('--' . $this->_boundary); - if ($this->sendAs === 'text') { - $prefix[] = 'Content-Type: text/plain; charset=' . $this->charset; - } elseif ($this->sendAs === 'html') { - $prefix[] = 'Content-Type: text/html; charset=' . $this->charset; - } elseif ($this->sendAs === 'both') { - $prefix[] = 'Content-Type: multipart/alternative; boundary="alt-' . $this->_boundary . '"'; - } - $prefix[] = 'Content-Transfer-Encoding: 7bit'; - $prefix[] = ''; - $message = array_merge($prefix, $message); - } - return $message; - } - -/** - * Attach files by adding file contents inside boundaries. - * - * @access private - * @TODO: modify to use the core File class? - */ - function _attachFiles() { + protected function _formatAttachFiles() { $files = array(); foreach ($this->attachments as $filename => $attachment) { $file = $this->_findFiles($attachment); @@ -673,21 +418,7 @@ class EmailComponent extends Component { $files[$filename] = $file; } } - - foreach ($files as $filename => $file) { - $handle = fopen($file, 'rb'); - $data = fread($handle, filesize($file)); - $data = chunk_split(base64_encode($data)) ; - fclose($handle); - - $this->_message[] = '--' . $this->_boundary; - $this->_message[] = 'Content-Type: application/octet-stream'; - $this->_message[] = 'Content-Transfer-Encoding: base64'; - $this->_message[] = 'Content-Disposition: attachment; filename="' . basename($filename) . '"'; - $this->_message[] = ''; - $this->_message[] = $data; - $this->_message[] = ''; - } + return $files; } /** @@ -710,39 +441,6 @@ class EmailComponent extends Component { return null; } -/** - * Wrap the message using EmailComponent::$lineLength - * - * @param string $message Message to wrap - * @param integer $lineLength Max length of line - * @return array Wrapped message - * @access protected - */ - function _wrap($message, $lineLength = null) { - $message = $this->_strip($message, true); - $message = str_replace(array("\r\n","\r"), "\n", $message); - $lines = explode("\n", $message); - $formatted = array(); - - if ($this->_lineLength !== null) { - trigger_error(__d('cake_dev', '_lineLength cannot be accessed please use lineLength'), E_USER_WARNING); - $this->lineLength = $this->_lineLength; - } - - if (!$lineLength) { - $lineLength = $this->lineLength; - } - - foreach ($lines as $line) { - if (substr($line, 0, 1) == '.') { - $line = '.' . $line; - } - $formatted = array_merge($formatted, explode("\n", wordwrap($line, $lineLength, "\n", true))); - } - $formatted[] = ''; - return $formatted; - } - /** * Encode the specified string using the current charset * @@ -770,24 +468,22 @@ class EmailComponent extends Component { } /** - * Format a string as an email address + * Format addresses to be an array with email as key and alias as value * - * @param string $string String representing an email address - * @return string Email address suitable for email headers or smtp pipe - * @access private + * @param array $addresses + * @return array */ - function _formatAddress($string, $smtp = false) { - $hasAlias = preg_match('/((.*))?\s?<(.+)>/', $string, $matches); - if ($smtp && $hasAlias) { - return $this->_strip('<' . $matches[3] . '>'); - } elseif ($smtp) { - return $this->_strip('<' . $string . '>'); + protected function _formatAddresses($addresses) { + $formatted = array(); + foreach ($addresses as $address) { + if (preg_match('/((.*))?\s?<(.+)>/', $address, $matches) && !empty($matches[2])) { + $formatted[$this->_strip($matches[3])] = $this->_encode($matches[2]); + } else { + $address = $this->_strip($address); + $formatted[$address] = $address; + } } - - if ($hasAlias && !empty($matches[2])) { - return $this->_encode($matches[2]) . $this->_strip(' <' . $matches[3] . '>'); - } - return $this->_strip($string); + return $formatted; } /** @@ -813,197 +509,4 @@ class EmailComponent extends Component { return $value; } -/** - * Wrapper for PHP mail function used for sending out emails - * - * @return bool Success - * @access private - */ - function _mail() { - $header = implode($this->lineFeed, $this->_header); - $message = implode($this->lineFeed, $this->_message); - if (is_array($this->to)) { - $to = implode(', ', array_map(array($this, '_formatAddress'), $this->to)); - } else { - $to = $this->to; - } - if (ini_get('safe_mode')) { - return @mail($to, $this->_encode($this->subject), $message, $header); - } - return @mail($to, $this->_encode($this->subject), $message, $header, $this->additionalParams); - } - - -/** - * Helper method to get socket, overridden in tests - * - * @param array $config Config data for the socket. - * @return void - * @access protected - */ - function _getSocket($config) { - $this->_smtpConnection = new CakeSocket($config); - } - -/** - * Sends out email via SMTP - * - * @return bool Success - * @access private - */ - function _smtp() { - App::uses('CakeSocket', 'Network'); - - $defaults = array( - 'host' => 'localhost', - 'port' => 25, - 'protocol' => 'smtp', - 'timeout' => 30 - ); - $this->smtpOptions = array_merge($defaults, $this->smtpOptions); - $this->_getSocket($this->smtpOptions); - - if (!$this->_smtpConnection->connect()) { - $this->smtpError = $this->_smtpConnection->lastError(); - return false; - } elseif (!$this->_smtpSend(null, '220')) { - return false; - } - - $httpHost = env('HTTP_HOST'); - - if (isset($this->smtpOptions['client'])) { - $host = $this->smtpOptions['client']; - } elseif (!empty($httpHost)) { - list($host) = explode(':', $httpHost); - } else { - $host = 'localhost'; - } - - if (!$this->_smtpSend("EHLO {$host}", '250') && !$this->_smtpSend("HELO {$host}", '250')) { - return false; - } - - if (isset($this->smtpOptions['username']) && isset($this->smtpOptions['password'])) { - $authRequired = $this->_smtpSend('AUTH LOGIN', '334|503'); - if ($authRequired == '334') { - if (!$this->_smtpSend(base64_encode($this->smtpOptions['username']), '334')) { - return false; - } - if (!$this->_smtpSend(base64_encode($this->smtpOptions['password']), '235')) { - return false; - } - } elseif ($authRequired != '503') { - return false; - } - } - - if (!$this->_smtpSend('MAIL FROM: ' . $this->_formatAddress($this->from, true))) { - return false; - } - - if (!is_array($this->to)) { - $tos = array_map('trim', explode(',', $this->to)); - } else { - $tos = $this->to; - } - foreach ($tos as $to) { - if (!$this->_smtpSend('RCPT TO: ' . $this->_formatAddress($to, true))) { - return false; - } - } - - foreach ($this->cc as $cc) { - if (!$this->_smtpSend('RCPT TO: ' . $this->_formatAddress($cc, true))) { - return false; - } - } - foreach ($this->bcc as $bcc) { - if (!$this->_smtpSend('RCPT TO: ' . $this->_formatAddress($bcc, true))) { - return false; - } - } - - if (!$this->_smtpSend('DATA', '354')) { - return false; - } - - $header = implode("\r\n", $this->_header); - $message = implode("\r\n", $this->_message); - if (!$this->_smtpSend($header . "\r\n\r\n" . $message . "\r\n\r\n\r\n.")) { - return false; - } - $this->_smtpSend('QUIT', false); - - $this->_smtpConnection->disconnect(); - return true; - } - -/** - * Protected method for sending data to SMTP connection - * - * @param string $data data to be sent to SMTP server - * @param mixed $checkCode code to check for in server response, false to skip - * @return bool Success - * @access protected - */ - function _smtpSend($data, $checkCode = '250') { - if (!is_null($data)) { - $this->_smtpConnection->write($data . "\r\n"); - } - while ($checkCode !== false) { - $response = ''; - $startTime = time(); - while (substr($response, -2) !== "\r\n" && ((time() - $startTime) < $this->smtpOptions['timeout'])) { - $response .= $this->_smtpConnection->read(); - } - if (substr($response, -2) !== "\r\n") { - $this->smtpError = 'timeout'; - return false; - } - $response = end(explode("\r\n", rtrim($response, "\r\n"))); - - if (preg_match('/^(' . $checkCode . ')(.)/', $response, $code)) { - if ($code[2] === '-') { - continue; - } - return $code[1]; - } - $this->smtpError = $response; - return false; - } - return true; - } - -/** - * Set as controller flash message a debug message showing current settings in component - * - * @return boolean Success - * @access private - */ - function _debug() { - $nl = "\n"; - $header = implode($nl, $this->_header); - $message = implode($nl, $this->_message); - $fm = '
';
-
-		if (is_array($this->to)) {
-			$to = implode(', ', array_map(array($this, '_formatAddress'), $this->to));
-		} else {
-			$to = $this->to;
-		}
-		$fm .= sprintf('%s %s%s', 'To:', $to, $nl);
-		$fm .= sprintf('%s %s%s', 'From:', $this->from, $nl);
-		$fm .= sprintf('%s %s%s', 'Subject:', $this->_encode($this->subject), $nl);
-		$fm .= sprintf('%s%3$s%3$s%s', 'Header:', $header, $nl);
-		$fm .= sprintf('%s%3$s%3$s%s', 'Parameters:', $this->additionalParams, $nl);
-		$fm .= sprintf('%s%3$s%3$s%s', 'Message:', $message, $nl);
-		$fm .= '
'; - - if (isset($this->Controller->Session)) { - $this->Controller->Session->setFlash($fm, 'default', null, 'email'); - return true; - } - return $fm; - } } diff --git a/lib/Cake/Controller/Component/RequestHandlerComponent.php b/lib/Cake/Controller/Component/RequestHandlerComponent.php index 56cf6c448..52843d60b 100644 --- a/lib/Cake/Controller/Component/RequestHandlerComponent.php +++ b/lib/Cake/Controller/Component/RequestHandlerComponent.php @@ -565,7 +565,6 @@ class RequestHandlerComponent extends Component { $defaults = array('index' => null, 'charset' => null, 'attachment' => false); $options = $options + $defaults; - $cType = null; if (strpos($type, '/') === false) { $cType = $this->response->getMimeType($type); if ($cType === false) { diff --git a/lib/Cake/Controller/ComponentCollection.php b/lib/Cake/Controller/ComponentCollection.php index 909fd70e1..47b6f603f 100644 --- a/lib/Cake/Controller/ComponentCollection.php +++ b/lib/Cake/Controller/ComponentCollection.php @@ -32,7 +32,7 @@ class ComponentCollection extends ObjectCollection { * Initializes all the Components for a controller. * Attaches a reference of each component to the Controller. * - * @param Controller $controller Controller to initialize components for. + * @param Controller $Controller Controller to initialize components for. * @return void */ public function init(Controller $Controller) { diff --git a/lib/Cake/Controller/Controller.php b/lib/Cake/Controller/Controller.php index 697629387..abc734905 100644 --- a/lib/Cake/Controller/Controller.php +++ b/lib/Cake/Controller/Controller.php @@ -353,7 +353,7 @@ class Controller extends Object { } /** - * Provides backwards compatbility access to the request object properties. + * Provides backwards compatibility access to the request object properties. * Also provides the params alias. * * @return void @@ -376,7 +376,7 @@ class Controller extends Object { } /** - * Provides backwards compatiblity access for setting values to the request object. + * Provides backwards compatibility access for setting values to the request object. * * @return void */ @@ -732,8 +732,6 @@ class Controller extends Object { * @link http://book.cakephp.org/view/979/set */ public function set($one, $two = null) { - $data = array(); - if (is_array($one)) { if (is_array($two)) { $data = array_combine($one, $two); diff --git a/lib/Cake/Core/App.php b/lib/Cake/Core/App.php index f7c49e0f5..e5c33a8e0 100644 --- a/lib/Cake/Core/App.php +++ b/lib/Cake/Core/App.php @@ -289,7 +289,10 @@ class App { '%s' . 'locale' . DS ), 'vendors' => array('%s' . 'vendors' . DS, VENDORS), - 'plugins' => array(APP . 'plugins' . DS, CAKE_CORE_INCLUDE_PATH . DS . 'plugins' . DS) + 'plugins' => array( + APP . 'plugins' . DS, + dirname(dirname(CAKE)) . DS . 'plugins' . DS + ) ); } @@ -320,9 +323,6 @@ class App { } } - $mergeExclude = array('Lib', 'locales', 'vendors', 'plugins'); - $appLibs = empty($paths['Lib']) ? $defaults['Lib'] : $paths['Lib']; - foreach ($defaults as $type => $default) { if (empty(self::$__packages[$type]) || empty($paths)) { self::$__packages[$type] = $default; @@ -408,7 +408,6 @@ class App { * @return mixed Either false on incorrect / miss. Or an array of found objects. */ public static function objects($type, $path = null, $cache = true) { - $objects = array(); $extension = '/\.php$/'; $includeDirectories = false; $name = $type; @@ -448,8 +447,6 @@ class App { $path = self::path($type, $plugin); } - $items = array(); - foreach ((array)$path as $dir) { if ($dir != APP && is_dir($dir)) { $files = new RegexIterator(new DirectoryIterator($dir), $extension); @@ -525,45 +522,47 @@ class App { * @param string $className the name of the class to load */ public static function load($className) { - if (isset(self::$__classMap[$className])) { - if ($file = self::__mapped($className)) { + if (!isset(self::$__classMap[$className])) { + return false; + } + + if ($file = self::__mapped($className)) { + return include $file; + } + + $parts = explode('.', self::$__classMap[$className], 2); + list($plugin, $package) = count($parts) > 1 ? $parts : array(null, current($parts)); + $paths = self::path($package, $plugin); + + if (empty($plugin)) { + $appLibs = empty(self::$__packages['Lib']) ? APPLIBS : current(self::$__packages['Lib']); + $paths[] = $appLibs . $package . DS; + $paths[] = LIBS . $package . DS; + } + + foreach ($paths as $path) { + $file = $path . $className . '.php'; + if (file_exists($file)) { + self::__map($file, $className); return include $file; } + } - $parts = explode('.', self::$__classMap[$className], 2); - list($plugin, $package) = count($parts) > 1 ? $parts : array(null, current($parts)); - $paths = self::path($package, $plugin); - - if (empty($plugin)) { - $appLibs = empty(self::$__packages['Lib']) ? APPLIBS : current(self::$__packages['Lib']); - $paths[] = $appLibs . $package . DS; - $paths[] = LIBS . $package . DS; + //To help apps migrate to 2.0 old style file names are allowed + foreach ($paths as $path) { + $underscored = Inflector::underscore($className); + $tries = array($path . $underscored . '.php'); + $parts = explode('_', $underscored); + if (count($parts) > 1) { + array_pop($parts); + $tries[] = $path . implode('_', $parts) . '.php'; } - - foreach ($paths as $path) { - $file = $path . $className . '.php'; + foreach ($tries as $file) { if (file_exists($file)) { self::__map($file, $className); return include $file; } } - - //To help apps migrate to 2.0 old style file names are allowed - foreach ($paths as $path) { - $underscored = Inflector::underscore($className); - $tries = array($path . $underscored . '.php'); - $parts = explode('_', $underscored); - if (count($parts) > 1) { - array_pop($parts); - $tries[] = $path . implode('_', $parts) . '.php'; - } - foreach ($tries as $file) { - if (file_exists($file)) { - self::__map($file, $className); - return include $file; - } - } - } } return false; @@ -588,7 +587,7 @@ class App { * @return boolean true if Class is already in memory or if file is found and loaded, false if not */ public static function import($type = null, $name = null, $parent = true, $search = array(), $file = null, $return = false) { - $ext = $plugin = $directory = null; + $ext = null; if (is_array($type)) { extract($type, EXTR_OVERWRITE); diff --git a/lib/Cake/Error/exceptions.php b/lib/Cake/Error/exceptions.php index 1145669fb..8affae940 100644 --- a/lib/Cake/Error/exceptions.php +++ b/lib/Cake/Error/exceptions.php @@ -467,8 +467,8 @@ class CakeSessionException extends CakeException { } class ConfigureException extends CakeException { } /** - * Exception class for Socket. This exception will be thrown from CakeSocket, HttpSocket and HttpResponse when it - * encounters an error. + * Exception class for Socket. This exception will be thrown from CakeSocket, CakeEmail, HttpSocket + * and HttpResponse when it encounters an error. * * @package cake.libs */ diff --git a/lib/Cake/I18n/Multibyte.php b/lib/Cake/I18n/Multibyte.php index 9ad06c093..122e1f123 100644 --- a/lib/Cake/I18n/Multibyte.php +++ b/lib/Cake/I18n/Multibyte.php @@ -772,7 +772,6 @@ class Multibyte { $length = count($utf8Map); $lowerCase = array(); - $matched = false; for ($i = 0 ; $i < $length; $i++) { $char = $utf8Map[$i]; @@ -819,7 +818,6 @@ class Multibyte { $utf8Map = Multibyte::utf8($string); $length = count($utf8Map); - $matched = false; $replaced = array(); $upperCase = array(); @@ -947,7 +945,6 @@ class Multibyte { } $string = Multibyte::utf8($string); - $stringCount = count($string); for ($i = 1; $i <= $start; $i++) { unset($string[$i - 1]); @@ -1068,7 +1065,6 @@ class Multibyte { * @return array */ private static function __find($char, $type = 'lower') { - $value = false; $found = array(); if (!isset(self::$__codeRange[$char])) { $range = self::__codepoint($char); diff --git a/lib/Cake/Model/Datasource/Session/CacheSession.php b/lib/Cake/Model/Datasource/Session/CacheSession.php index 9b1b4ded0..29cacc218 100644 --- a/lib/Cake/Model/Datasource/Session/CacheSession.php +++ b/lib/Cake/Model/Datasource/Session/CacheSession.php @@ -16,6 +16,9 @@ * @since CakePHP(tm) v 2.0 * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ + +App::uses('Cache', 'Cache'); + /** * CacheSession provides method for saving sessions into a Cache engine. Used with CakeSession * diff --git a/lib/Cake/Model/Model.php b/lib/Cake/Model/Model.php index 8ed3b3ca9..63f1f6017 100644 --- a/lib/Cake/Model/Model.php +++ b/lib/Cake/Model/Model.php @@ -2589,7 +2589,7 @@ class Model extends Object { 'allowEmpty' => null, 'required' => null, 'rule' => 'blank', - 'last' => false, + 'last' => true, 'on' => null ); @@ -2728,7 +2728,7 @@ class Model extends Object { if (!is_array($this->validationErrors)) { $this->validationErrors = array(); } - $this->validationErrors[$field] = $value; + $this->validationErrors[$field] []= $value; } /** diff --git a/lib/Cake/Network/CakeEmail.php b/lib/Cake/Network/CakeEmail.php new file mode 100644 index 000000000..21c1540a9 --- /dev/null +++ b/lib/Cake/Network/CakeEmail.php @@ -0,0 +1,1334 @@ +charset = $charset; + } + } + +/** + * From + * + * @param mixed $email + * @param string $name + * @return mixed + * @thrown SocketException + */ + public function from($email = null, $name = null) { + if ($email === null) { + return $this->_from; + } + return $this->_setEmailSingle('_from', $email, $name, __d('cake', 'From requires only 1 email address.')); + } + +/** + * Sender + * + * @param mixed $email + * @param string $name + * @return mixed + * @thrown SocketException + */ + public function sender($email = null, $name = null) { + if ($email === null) { + return $this->_sender; + } + return $this->_setEmailSingle('_sender', $email, $name, __d('cake', 'Sender requires only 1 email address.')); + } + +/** + * Reply-To + * + * @param mixed $email + * @param string $name + * @return mixed + * @thrown SocketException + */ + public function replyTo($email = null, $name = null) { + if ($email === null) { + return $this->_replyTo; + } + return $this->_setEmailSingle('_replyTo', $email, $name, __d('cake', 'Reply-To requires only 1 email address.')); + } + +/** + * Read Receipt (Disposition-Notification-To header) + * + * @param mixed $email + * @param string $name + * @return mixed + * @thrown SocketException + */ + public function readReceipt($email = null, $name = null) { + if ($email === null) { + return $this->_readReceipt; + } + return $this->_setEmailSingle('_readReceipt', $email, $name, __d('cake', 'Disposition-Notification-To requires only 1 email address.')); + } + +/** + * Return Path + * + * @param mixed $email + * @param string $name + * @return mixed + * @thrown SocketException + */ + public function returnPath($email = null, $name = null) { + if ($email === null) { + return $this->_returnPath; + } + return $this->_setEmailSingle('_returnPath', $email, $name, __d('cake', 'Return-Path requires only 1 email address.')); + } + +/** + * To + * + * @param mixed $email Null to get, String with email, Array with email as key, name as value or email as value (without name) + * @param string $name + * @return mixed + */ + public function to($email = null, $name = null) { + if ($email === null) { + return $this->_to; + } + return $this->_setEmail('_to', $email, $name); + } + +/** + * Add To + * + * @param mixed $email String with email, Array with email as key, name as value or email as value (without name) + * @param string $name + * @return object $this + */ + public function addTo($email, $name = null) { + return $this->_addEmail('_to', $email, $name); + } + +/** + * Cc + * + * @param mixed $email String with email, Array with email as key, name as value or email as value (without name) + * @param string $name + * @return mixed + */ + public function cc($email = null, $name = null) { + if ($email === null) { + return $this->_cc; + } + return $this->_setEmail('_cc', $email, $name); + } + +/** + * Add Cc + * + * @param mixed $email String with email, Array with email as key, name as value or email as value (without name) + * @param string $name + * @return object $this + */ + public function addCc($email, $name = null) { + return $this->_addEmail('_cc', $email, $name); + } + +/** + * Bcc + * + * @param mixed $email String with email, Array with email as key, name as value or email as value (without name) + * @param string $name + * @return mixed + */ + public function bcc($email = null, $name = null) { + if ($email === null) { + return $this->_bcc; + } + return $this->_setEmail('_bcc', $email, $name); + } + +/** + * Add Bcc + * + * @param mixed $email String with email, Array with email as key, name as value or email as value (without name) + * @param string $name + * @return object $this + */ + public function addBcc($email, $name = null) { + return $this->_addEmail('_bcc', $email, $name); + } + +/** + * Set email + * + * @param string $varName + * @param mixed $email + * @param mixed $name + * @return object $this + * @thrown SocketException + */ + protected function _setEmail($varName, $email, $name) { + if (!is_array($email)) { + if (!Validation::email($email)) { + throw new SocketException(__d('cake', 'Invalid email: "%s"', $email)); + } + if ($name === null) { + $name = $email; + } + $this->{$varName} = array($email => $name); + return $this; + } + $list = array(); + foreach ($email as $key => $value) { + if (is_int($key)) { + $key = $value; + } + if (!Validation::email($key)) { + throw new SocketException(__d('cake', 'Invalid email: "%s"', $key)); + } + $list[$key] = $value; + } + $this->{$varName} = $list; + return $this; + } + +/** + * Set only 1 email + * + * @param string $varName + * @param mixed $email + * @param string $name + * @param string $throwMessage + * @return object $this + * @thrown SocketExpceiton + */ + protected function _setEmailSingle($varName, $email, $name, $throwMessage) { + $current = $this->{$varName}; + $this->_setEmail($varName, $email, $name); + if (count($this->{$varName}) !== 1) { + $this->{$varName} = $current; + throw new SocketException($throwMessage); + } + return $this; + } + +/** + * Add email + * + * @param string $varName + * @param mixed $email + * @param mixed $name + * @return object $this + */ + protected function _addEmail($varName, $email, $name) { + if (!is_array($email)) { + if (!Validation::email($email)) { + throw new SocketException(__d('cake', 'Invalid email: "%s"', $email)); + } + if ($name === null) { + $name = $email; + } + $this->{$varName}[$email] = $name; + return $this; + } + $list = array(); + foreach ($email as $key => $value) { + if (is_int($key)) { + $key = $value; + } + if (!Validation::email($key)) { + throw new SocketException(__d('cake', 'Invalid email: "%s"', $key)); + } + $list[$key] = $value; + } + $this->{$varName} = array_merge($this->{$varName}, $list); + return $this; + } + +/** + * Set Subject + * + * @param string $subject + * @return mixed + */ + public function subject($subject = null) { + if ($subject === null) { + return $this->_subject; + } + $this->_subject = $this->_encode((string)$subject); + return $this; + } + +/** + * Sets headers for the message + * + * @param array Associative array containing headers to be set. + * @return object $this + * @thrown SocketException + */ + public function setHeaders($headers) { + if (!is_array($headers)) { + throw new SocketException(__d('cake', '$headers should be an array.')); + } + $this->_headers = $headers; + return $this; + } + +/** + * Add header for the message + * + * @param array $headers + * @return mixed $this + * @thrown SocketException + */ + public function addHeaders($headers) { + if (!is_array($headers)) { + throw new SocketException(__d('cake', '$headers should be an array.')); + } + $this->_headers = array_merge($this->_headers, $headers); + return $this; + } + +/** + * Get list of headers + * + * ### Includes: + * + * - `from` + * - `replyTo` + * - `readReceipt` + * - `returnPath` + * - `to` + * - `cc` + * - `bcc` + * - `subject` + * + * @param array $include + * @return array + */ + public function getHeaders($include = array()) { + $defaults = array( + 'from' => false, + 'sender' => false, + 'replyTo' => false, + 'readReceipt' => false, + 'returnPath' => false, + 'to' => false, + 'cc' => false, + 'bcc' => false, + 'subject' => false + ); + $include += $defaults; + + $headers = array(); + $relation = array( + 'from' => 'From', + 'replyTo' => 'Reply-To', + 'readReceipt' => 'Disposition-Notification-To', + 'returnPath' => 'Return-Path' + ); + foreach ($relation as $var => $header) { + if ($include[$var]) { + $var = '_' . $var; + $headers[$header] = current($this->_formatAddress($this->{$var})); + } + } + if ($include['sender']) { + if (key($this->_sender) === key($this->_from)) { + $headers['Sender'] = ''; + } else { + $headers['Sender'] = current($this->_formatAddress($this->_sender)); + } + } + + foreach (array('to', 'cc', 'bcc') as $var) { + if ($include[$var]) { + $classVar = '_' . $var; + $headers[ucfirst($var)] = implode(', ', $this->_formatAddress($this->{$classVar})); + } + } + + $headers += $this->_headers; + if (!isset($headers['X-Mailer'])) { + $headers['X-Mailer'] = self::EMAIL_CLIENT; + } + if (!isset($headers['Date'])) { + $headers['Date'] = date(DATE_RFC2822); + } + if ($this->_messageId !== false) { + if ($this->_messageId === true) { + $headers['Message-ID'] = '<' . String::UUID() . '@' . env('HTTP_HOST') . '>'; + } else { + $headers['Message-ID'] = $this->_messageId; + } + } + + if ($include['subject']) { + $headers['Subject'] = $this->_subject; + } + + $headers['MIME-Version'] = '1.0'; + if (!empty($this->_attachments)) { + $headers['Content-Type'] = 'multipart/mixed; boundary="' . $this->_boundary . '"'; + $headers[] = 'This part of the E-mail should never be seen. If'; + $headers[] = 'you are reading this, consider upgrading your e-mail'; + $headers[] = 'client to a MIME-compatible client.'; + } elseif ($this->_emailFormat === 'text') { + $headers['Content-Type'] = 'text/plain; charset=' . $this->charset; + } elseif ($this->_emailFormat === 'html') { + $headers['Content-Type'] = 'text/html; charset=' . $this->charset; + } elseif ($this->_emailFormat === 'both') { + $headers['Content-Type'] = 'multipart/alternative; boundary="alt-' . $this->_boundary . '"'; + } + $headers['Content-Transfer-Encoding'] = '7bit'; + + return $headers; + } + +/** + * Format addresses + * + * @param array $address + * @return array + */ + protected function _formatAddress($address) { + $return = array(); + foreach ($address as $email => $alias) { + if ($email === $alias) { + $return[] = $email; + } else { + $return[] = sprintf('%s <%s>', $this->_encode($alias), $email); + } + } + return $return; + } + +/** + * Template and layout + * + * @param mixed $template Template name or null to not use + * @param mixed $layout Layout name or null to not use + * @return mixed + */ + public function template($template = false, $layout = false) { + if ($template === false) { + return array( + 'template' => $this->_template, + 'layout' => $this->_layout + ); + } + $this->_template = $template; + if ($layout !== false) { + $this->_layout = $layout; + } + return $this; + } + +/** + * View class for render + * + * @param string $viewClass + * @return mixed + */ + public function viewRender($viewClass = null) { + if ($viewClass === null) { + return $this->_viewRender; + } + $this->_viewRender = $viewClass; + return $this; + } + +/** + * Variables to be set on render + * + * @param array $viewVars + * @return mixed + */ + public function viewVars($viewVars = null) { + if ($viewVars === null) { + return $this->_viewVars; + } + $this->_viewVars = array_merge($this->_viewVars, (array)$viewVars); + return $this; + } + +/** + * Email format + * + * @param string $format + * @return mixed + * @thrown SocketException + */ + public function emailFormat($format = null) { + if ($format === null) { + return $this->_emailFormat; + } + if (!in_array($format, $this->_emailFormatAvailable)) { + throw new SocketException(__d('cake', 'Format not available.')); + } + $this->_emailFormat = $format; + return $this; + } + +/** + * Transport name + * + * @param string $name + * @return mixed + */ + public function transport($name = null) { + if ($name === null) { + return $this->_transportName; + } + $this->_transportName = (string)$name; + $this->_transportClass = null; + return $this; + } + +/** + * Return the transport class + * + * @return object + * @thrown SocketException + */ + public function transportClass() { + if ($this->_transportClass) { + return $this->_transportClass; + } + list($plugin, $transportClassname) = pluginSplit($this->_transportName, true); + $transportClassname .= 'Transport'; + App::uses($transportClassname, $plugin . 'Network/Email'); + if (!class_exists($transportClassname)) { + throw new SocketException(__d('cake', 'Class "%s" not found.', $transportClassname)); + } elseif (!method_exists($transportClassname, 'send')) { + throw new SocketException(__d('cake', 'The "%s" do not have send method.', $transportClassname)); + } + + return $this->_transportClass = new $transportClassname(); + } + +/** + * Message-ID + * + * @param mixed $message True to generate a new Message-ID, False to ignore (not send in email), String to set as Message-ID + * @return mixed + * @thrown SocketException + */ + public function messageId($message = null) { + if ($message === null) { + return $this->_messageId; + } + if (is_bool($message)) { + $this->_messageId = $message; + } else { + if (!preg_match('/^\<.+@.+\>$/', $message)) { + throw new SocketException(__d('cake', 'Invalid format to Message-ID. The text should be something like ""')); + } + $this->_messageId = $message; + } + return $this; + } + +/** + * Attachments + * + * @param mixed $attachments String with the filename or array with filenames + * @return mixed + * @thrown SocketException + */ + public function attachments($attachments = null) { + if ($attachments === null) { + return $this->_attachments; + } + $attach = array(); + foreach ((array)$attachments as $name => $fileInfo) { + if (!is_array($fileInfo)) { + $fileInfo = array('file' => $fileInfo); + } + if (!isset($fileInfo['file'])) { + throw new SocketException(__d('cake', 'File not specified.')); + } + $fileInfo['file'] = realpath($fileInfo['file']); + if ($fileInfo['file'] === false || !file_exists($fileInfo['file'])) { + throw new SocketException(__d('cake', 'File not found: "%s"', $fileInfo['file'])); + } + if (is_int($name)) { + $name = basename($fileInfo['file']); + } + if (!isset($fileInfo['mimetype'])) { + $fileInfo['mimetype'] = 'application/octet-stream'; + } + $attach[$name] = $fileInfo; + } + $this->_attachments = $attach; + return $this; + } + +/** + * Add attachments + * + * @param mixed $attachments String with the filename or array with filenames + * @return object $this + * @thrown SocketException + */ + public function addAttachments($attachments) { + $current = $this->_attachments; + $this->attachments($attachments); + $this->_attachments = array_merge($current, $this->_attachments); + return $this; + } + +/** + * Get generated message (used by transport classes) + * + * @param mixed $type Use MESSAGE_* constants or null to return the full message as array + * @return mixed String if have type, array if type is null + */ + public function message($type = null) { + switch ($type) { + case self::MESSAGE_HTML: + return $this->_htmlMessage; + case self::MESSAGE_TEXT: + return $this->_textMessage; + } + return $this->_message; + } + +/** + * Configuration to use when send email + * + * @param mixed $config String with configuration name (from email.php), array with config or null to return current config + * @return mixed + */ + public function config($config = null) { + if ($config === null) { + return $this->_config; + } + + if (is_array($config)) { + $this->_config = $config; + } else { + $this->_config = (string)$config; + } + + if ($this->_transportClass) { + $this->_transportClass->config($this->_config); + } + + return $this; + } + +/** + * Send an email using the specified content, template and layout + * + * @return boolean Success + * @thrown SocketException + */ + public function send($content = null) { + if (is_string($this->_config)) { + if (!config('email')) { + throw new SocketException(__d('cake', '%s not found.', CONFIGS . 'email.php')); + } + $configs = new EmailConfig(); + if (!isset($configs->{$this->_config})) { + throw new SocketException(__d('cake', 'Unknown email configuration "%s".', $this->_config)); + } + $config = $configs->{$this->_config}; + if (isset($config['transport'])) { + $this->transport($config['transport']); + } + } else { + $config = $this->_config; + } + + if (empty($this->_from)) { + if (!empty($config['from'])) { + $this->from($config['from']); + } else { + throw new SocketException(__d('cake', 'From is not specified.')); + } + } + if (empty($this->_to) && empty($this->_cc) && empty($this->_bcc)) { + throw new SocketException(__d('cake', 'You need specify one destination on to, cc or bcc.')); + } + + if (is_array($content)) { + $content = implode("\n", $content) . "\n"; + } + + $this->_textMessage = $this->_htmlMessage = ''; + if ($content !== null) { + if ($this->_emailFormat === 'text') { + $this->_textMessage = $content; + } elseif ($this->_emailFormat === 'html') { + $this->_htmlMessage = $content; + } elseif ($this->_emailFormat === 'both') { + $this->_textMessage = $this->_htmlMessage = $content; + } + } + + $this->_createBoundary(); + + $message = $this->_wrap($content); + if (empty($this->_template)) { + $message = $this->_formatMessage($message); + } else { + $message = $this->_render($message); + } + $message[] = ''; + $this->_message = $message; + + if (!empty($this->_attachments)) { + $this->_attachFiles(); + + $this->_message[] = ''; + $this->_message[] = '--' . $this->_boundary . '--'; + $this->_message[] = ''; + } + + $transport = $this->transportClass(); + $transport->config($config); + + return $transport->send($this); + } + +/** + * Static method to fast create an instance of CakeEmail + * + * @param mixed $to Address to send (see CakeEmail::to()). If null, will try to use 'to' from transport config + * @param mixed $subject String of subject or null to use 'subject' from transport config + * @param mixed $message String with message or array with variables to be used in render + * @param mixed $transportConfig String to use config from EmailConfig or array with configs + * @param boolean $send Send the email or just return the instance pre-configured + * @return object Instance of CakeEmail + */ + public static function deliver($to = null, $subject = null, $message = null, $transportConfig = 'fast', $send = true) { + $class = __CLASS__; + $instance = new $class(); + + if (is_string($transportConfig)) { + if (!config('email')) { + throw new SocketException(__d('cake', '%s not found.', CONFIGS . 'email.php')); + } + $configs = new EmailConfig(); + if (!isset($configs->{$transportConfig})) { + throw new SocketException(__d('cake', 'Unknown email configuration "%s".', $transportConfig)); + } + $transportConfig = $configs->{$transportConfig}; + } + self::_applyConfig($instance, $transportConfig); + + if ($to !== null) { + $instance->to($to); + } + if ($subject !== null) { + $instance->subject($subject); + } + if (is_array($message)) { + $instance->viewVars($message); + $message = null; + } elseif ($message === null && isset($config['message'])) { + $message = $config['message']; + } + + if ($send === true) { + $instance->send($message); + } + + return $instance; + } + +/** + * Apply the config to an instance + * + * @param object $obj CakeEmail + * @param array $config + * @return void + */ + protected static function _applyConfig(CakeEmail $obj, $config) { + $simpleMethods = array( + 'from', 'sender', 'to', 'replyTo', 'readReceipt', 'returnPath', 'cc', 'bcc', + 'messageId', 'subject', 'viewRender', 'viewVars', 'attachments', + 'transport', 'emailFormat' + ); + foreach ($simpleMethods as $method) { + if (isset($config[$method])) { + $obj->$method($config[$method]); + unset($config[$method]); + } + } + if (isset($config['headers'])) { + $obj->setHeaders($config['headers']); + unset($config['headers']); + } + if (array_key_exists('template', $config)) { + $layout = false; + if (array_key_exists('layout', $config)) { + $layout = $config['layout']; + unset($config['layout']); + } + $obj->template($config['template'], $layout); + unset($config['template']); + } + $obj->config($config); + } + +/** + * Reset all EmailComponent internal variables to be able to send out a new email. + * + * @return object $this + */ + public function reset() { + $this->_to = array(); + $this->_from = array(); + $this->_sender = array(); + $this->_replyTo = array(); + $this->_readReceipt = array(); + $this->_returnPath = array(); + $this->_cc = array(); + $this->_bcc = array(); + $this->_messageId = true; + $this->_subject = ''; + $this->_headers = array(); + $this->_layout = 'default'; + $this->_template = ''; + $this->_viewRender = 'View'; + $this->_viewVars = array(); + $this->_textMessage = ''; + $this->_htmlMessage = ''; + $this->_message = ''; + $this->_emailFormat = 'text'; + $this->_transportName = 'mail'; + $this->_transportClass = null; + $this->_attachments = array(); + $this->_config = 'default'; + return $this; + } + +/** + * Encode the specified string using the current charset + * + * @param string $text String to encode + * @return string Encoded string + */ + protected function _encode($text) { + $internalEncoding = function_exists('mb_internal_encoding'); + if ($internalEncoding) { + $restore = mb_internal_encoding(); + mb_internal_encoding($this->charset); + } + $return = mb_encode_mimeheader($text, $this->charset, 'B'); + if ($internalEncoding) { + mb_internal_encoding($restore); + } + return $return; + } + +/** + * Wrap the message to follow the RFC 2822 - 2.1.1 + * + * @param string $message Message to wrap + * @return array Wrapped message + */ + protected function _wrap($message) { + $message = str_replace(array("\r\n", "\r"), "\n", $message); + $lines = explode("\n", $message); + $formatted = array(); + + foreach ($lines as $line) { + if (empty($line)) { + $formatted[] = ''; + continue; + } + if ($line[0] === '.') { + $line = '.' . $line; + } + if (!preg_match('/\<[a-z]/i', $line)) { + $formatted = array_merge($formatted, explode("\n", wordwrap($line, self::LINE_LENGTH_SHOULD, "\n"))); + continue; + } + + $tagOpen = false; + $tmpLine = $tag = ''; + $tmpLineLength = 0; + for ($i = 0, $count = strlen($line); $i < $count; $i++) { + $char = $line[$i]; + if ($tagOpen) { + $tag .= $char; + if ($char === '>') { + $tagLength = strlen($tag); + if ($tagLength + $tmpLineLength < self::LINE_LENGTH_SHOULD) { + $tmpLine .= $tag; + $tmpLineLength += $tagLength; + } else { + if ($tmpLineLength > 0) { + $formatted[] = trim($tmpLine); + $tmpLine = ''; + $tmpLineLength = 0; + } + if ($tagLength > self::LINE_LENGTH_SHOULD) { + $formatted[] = $tag; + } else { + $tmpLine = $tag; + $tmpLineLength = $tagLength; + } + } + $tag = ''; + $tagOpen = false; + } + continue; + } + if ($char === '<') { + $tagOpen = true; + $tag = '<'; + continue; + } + if ($char === ' ' && $tmpLineLength >= self::LINE_LENGTH_SHOULD) { + $formatted[] = $tmpLine; + $tmpLineLength = 0; + continue; + } + $tmpLine .= $char; + $tmpLineLength++; + if ($tmpLineLength === self::LINE_LENGTH_SHOULD) { + $nextChar = $line[$i + 1]; + if ($nextChar === ' ' || $nextChar === '<') { + $formatted[] = trim($tmpLine); + $tmpLine = ''; + $tmpLineLength = 0; + if ($nextChar === ' ') { + $i++; + } + } else { + $lastSpace = strrpos($tmpLine, ' '); + if ($lastSpace === false) { + continue; + } + $formatted[] = trim(substr($tmpLine, 0, $lastSpace)); + $tmpLine = substr($tmpLine, $lastSpace + 1); + $tmpLineLength = strlen($tmpLine); + } + } + } + if (!empty($tmpLine)) { + $formatted[] = $tmpLine; + } + } + $formatted[] = ''; + return $formatted; + } + +/** + * Create unique boundary identifier + * + * @return void + */ + protected function _createBoundary() { + if (!empty($this->_attachments) || $this->_emailFormat === 'both') { + $this->_boundary = md5(uniqid(time())); + } + } + +/** + * Attach files by adding file contents inside boundaries. + * + * @return void + */ + protected function _attachFiles() { + foreach ($this->_attachments as $filename => $fileInfo) { + $handle = fopen($fileInfo['file'], 'rb'); + $data = fread($handle, filesize($fileInfo['file'])); + $data = chunk_split(base64_encode($data)) ; + fclose($handle); + + $this->_message[] = '--' . $this->_boundary; + $this->_message[] = 'Content-Type: ' . $fileInfo['mimetype']; + $this->_message[] = 'Content-Transfer-Encoding: base64'; + if (empty($fileInfo['contentId'])) { + $this->_message[] = 'Content-Disposition: attachment; filename="' . $filename . '"'; + } else { + $this->_message[] = 'Content-ID: <' . $fileInfo['contentId'] . '>'; + $this->_message[] = 'Content-Disposition: inline; filename="' . $filename . '"'; + } + $this->_message[] = ''; + $this->_message[] = $data; + $this->_message[] = ''; + } + } + +/** + * Format the message by seeing if it has attachments. + * + * @param array $message Message to format + * @return array + */ + protected function _formatMessage($message) { + if (!empty($this->_attachments)) { + $prefix = array('--' . $this->_boundary); + if ($this->_emailFormat === 'text') { + $prefix[] = 'Content-Type: text/plain; charset=' . $this->charset; + } elseif ($this->_emailFormat === 'html') { + $prefix[] = 'Content-Type: text/html; charset=' . $this->charset; + } elseif ($this->_emailFormat === 'both') { + $prefix[] = 'Content-Type: multipart/alternative; boundary="alt-' . $this->_boundary . '"'; + } + $prefix[] = 'Content-Transfer-Encoding: 7bit'; + $prefix[] = ''; + $message = array_merge($prefix, $message); + } + return $message; + } + +/** + * Render the contents using the current layout and template. + * + * @param string $content Content to render + * @return array Email ready to be sent + * @access private + */ + protected function _render($content) { + $viewClass = $this->_viewRender; + + if ($viewClass !== 'View') { + list($plugin, $viewClass) = pluginSplit($viewClass, true); + $viewClass .= 'View'; + App::uses($viewClass, $plugin . 'View'); + } + + $View = new $viewClass(null); + $View->viewVars = $this->_viewVars; + $msg = array(); + + $content = implode("\n", $content); + + if ($this->_emailFormat === 'both') { + $originalContent = $content; + if (!empty($this->_attachments)) { + $msg[] = '--' . $this->_boundary; + $msg[] = 'Content-Type: multipart/alternative; boundary="alt-' . $this->_boundary . '"'; + $msg[] = ''; + } + $msg[] = '--alt-' . $this->_boundary; + $msg[] = 'Content-Type: text/plain; charset=' . $this->charset; + $msg[] = 'Content-Transfer-Encoding: 7bit'; + $msg[] = ''; + + $View->viewPath = $View->layoutPath = 'emails' . DS . 'text'; + $View->viewVars['content'] = $originalContent; + $this->_textMessage = str_replace(array("\r\n", "\r"), "\n", $View->render($this->_template, $this->_layout)); + $content = explode("\n", $this->_textMessage); + $msg = array_merge($msg, $content); + + $msg[] = ''; + $msg[] = '--alt-' . $this->_boundary; + $msg[] = 'Content-Type: text/html; charset=' . $this->charset; + $msg[] = 'Content-Transfer-Encoding: 7bit'; + $msg[] = ''; + + $View->viewPath = $View->layoutPath = 'emails' . DS . 'html'; + $View->viewVars['content'] = $originalContent; + $View->hasRendered = false; + $this->_htmlMessage = str_replace(array("\r\n", "\r"), "\n", $View->render($this->_template, $this->_layout)); + $content = explode("\n", $this->_htmlMessage); + $msg = array_merge($msg, $content); + + $msg[] = ''; + $msg[] = '--alt-' . $this->_boundary . '--'; + $msg[] = ''; + + return $msg; + } + + if (!empty($this->_attachments)) { + if ($this->_emailFormat === 'html') { + $msg[] = ''; + $msg[] = '--' . $this->_boundary; + $msg[] = 'Content-Type: text/html; charset=' . $this->charset; + $msg[] = 'Content-Transfer-Encoding: 7bit'; + $msg[] = ''; + } else { + $msg[] = '--' . $this->_boundary; + $msg[] = 'Content-Type: text/plain; charset=' . $this->charset; + $msg[] = 'Content-Transfer-Encoding: 7bit'; + $msg[] = ''; + } + } + + $View->viewPath = $View->layoutPath = 'emails' . DS . $this->_emailFormat; + $View->viewVars['content'] = $content; + $rendered = $View->render($this->_template, $this->_layout); + $content = explode("\n", $rendered); + + if ($this->_emailFormat === 'html') { + $this->_htmlMessage = $rendered; + } else { + $this->_textMessage = $rendered; + } + + return array_merge($msg, $content); + } + +} diff --git a/lib/Cake/Network/CakeResponse.php b/lib/Cake/Network/CakeResponse.php index e1abb8a3d..3ed10258d 100644 --- a/lib/Cake/Network/CakeResponse.php +++ b/lib/Cake/Network/CakeResponse.php @@ -363,10 +363,12 @@ class CakeResponse { * @return void */ protected function _sendHeader($name, $value = null) { - if (is_null($value)) { - header($name); - } else { - header("{$name}: {$value}"); + if (!headers_sent()) { + if (is_null($value)) { + header($name); + } else { + header("{$name}: {$value}"); + } } } @@ -571,7 +573,6 @@ class CakeResponse { return array_map(array($this, 'mapType'), $ctype); } $keys = array_keys($this->_mimeTypes); - $count = count($keys); foreach ($this->_mimeTypes as $alias => $types) { if (is_array($types) && in_array($ctype, $types)) { diff --git a/lib/Cake/Network/Email/AbstractTransport.php b/lib/Cake/Network/Email/AbstractTransport.php new file mode 100644 index 000000000..a655eaded --- /dev/null +++ b/lib/Cake/Network/Email/AbstractTransport.php @@ -0,0 +1,75 @@ +_config = $config; + } + } + +/** + * Help to convert headers in string + * + * @param array $headers Headers in format key => value + * @param string $eol + * @return string + */ + protected function _headersToString($headers, $eol = "\r\n") { + $out = ''; + foreach ($headers as $key => $value) { + if ($value === false || $value === null || $value === '') { + continue; + } + $out .= $key . ': ' . $value . $eol; + } + if (!empty($out)) { + $out = substr($out, 0, -1 * strlen($eol)); + } + return $out; + } + +} diff --git a/lib/Cake/Network/Email/MailTransport.php b/lib/Cake/Network/Email/MailTransport.php new file mode 100644 index 000000000..0b6d3cda4 --- /dev/null +++ b/lib/Cake/Network/Email/MailTransport.php @@ -0,0 +1,49 @@ +_config['eol'])) { + $eol = $this->_config['eol']; + } + $headers = $email->getHeaders(array_fill_keys(array('from', 'sender', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'bcc'), true)); + $to = $headers['To']; + unset($headers['To']); + $header = $this->_headersToString($headers, $eol); + $message = implode($eol, $email->message()); + if (ini_get('safe_mode') || !isset($this->_config['additionalParameters'])) { + return @mail($to, $email->subject(), $message, $header); + } + return @mail($to, $email->subject(), $message, $header, $this->_config['additionalParameters']); + } + +} diff --git a/lib/Cake/Network/Email/SmtpTransport.php b/lib/Cake/Network/Email/SmtpTransport.php new file mode 100644 index 000000000..5cf6674b9 --- /dev/null +++ b/lib/Cake/Network/Email/SmtpTransport.php @@ -0,0 +1,221 @@ +_cakeEmail = $email; + + $this->_connect(); + $this->_auth(); + $this->_sendRcpt(); + $this->_sendData(); + $this->_disconnect(); + + return true; + } + +/** + * Set the configuration + * + * @param array $config + * @return object $this + */ + public function config($config = array()) { + $default = array( + 'host' => 'localhost', + 'port' => 25, + 'timeout' => 30, + 'username' => null, + 'password' => null, + 'client' => null + ); + $this->_config = $config + $default; + } + +/** + * Connect to SMTP Server + * + * @return void + * @thrown SocketException + */ + protected function _connect() { + $this->_generateSocket(); + if (!$this->_socket->connect()) { + throw new SocketException(__d('cake', 'Unable to connect in SMTP server.')); + } + $this->_smtpSend(null, '220'); + + if (isset($this->_config['client'])) { + $host = $this->_config['client']; + } elseif ($httpHost = env('HTTP_HOST')) { + list($host) = explode(':', $httpHost); + } else { + $host = 'localhost'; + } + + try { + $this->_smtpSend("EHLO {$host}", '250'); + } catch (SocketException $e) { + try { + $this->_smtpSend("HELO {$host}", '250'); + } catch (SocketException $e2) { + throw new SocketException(__d('cake', 'SMTP server not accepted the connection.')); + } + } + } + +/** + * Send authentication + * + * @return void + * @thrown SocketException + */ + protected function _auth() { + if (isset($this->_config['username']) && isset($this->_config['password'])) { + $authRequired = $this->_smtpSend('AUTH LOGIN', '334|503'); + if ($authRequired == '334') { + if (!$this->_smtpSend(base64_encode($this->_config['username']), '334')) { + throw new SocketException(__d('cake', 'SMTP server not accepted the username.')); + } + if (!$this->_smtpSend(base64_encode($this->_config['password']), '235')) { + throw new SocketException(__d('cake', 'SMTP server not accepted the password.')); + } + } elseif ($authRequired != '503') { + throw new SocketException(__d('cake', 'SMTP do not require authentication.')); + } + } + } + +/** + * Send emails + * + * @return void + * @thrown SocketException + */ + protected function _sendRcpt() { + $from = $this->_cakeEmail->from(); + $this->_smtpSend('MAIL FROM:<' . key($from) . '>'); + + $to = $this->_cakeEmail->to(); + $cc = $this->_cakeEmail->cc(); + $bcc = $this->_cakeEmail->bcc(); + $emails = array_merge(array_keys($to), array_keys($cc), array_keys($bcc)); + foreach ($emails as $email) { + $this->_smtpSend('RCPT TO:<' . $email . '>'); + } + } + +/** + * Send Data + * + * @return void + * @thrown SocketException + */ + protected function _sendData() { + $this->_smtpSend('DATA', '354'); + + $headers = $this->_cakeEmail->getHeaders(array_fill_keys(array('from', 'sender', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'bcc', 'subject'), true)); + $headers = $this->_headersToString($headers); + $message = implode("\r\n", $this->_cakeEmail->message()); + $this->_smtpSend($headers . "\r\n\r\n" . $message . "\r\n\r\n\r\n."); + } + +/** + * Disconnect + * + * @return void + * @thrown SocketException + */ + protected function _disconnect() { + $this->_smtpSend('QUIT', false); + $this->_socket->disconnect(); + } + +/** + * Helper method to generate socket + * + * @return void + * @thrown SocketException + */ + protected function _generateSocket() { + $this->_socket = new CakeSocket($this->_config); + } + +/** + * Protected method for sending data to SMTP connection + * + * @param string $data data to be sent to SMTP server + * @param mixed $checkCode code to check for in server response, false to skip + * @return void + * @thrown SocketException + */ + function _smtpSend($data, $checkCode = '250') { + if (!is_null($data)) { + $this->_socket->write($data . "\r\n"); + } + while ($checkCode !== false) { + $response = ''; + $startTime = time(); + while (substr($response, -2) !== "\r\n" && ((time() - $startTime) < $this->_config['timeout'])) { + $response .= $this->_socket->read(); + } + if (substr($response, -2) !== "\r\n") { + throw new SocketException(__d('cake', 'SMTP timeout.')); + } + $response = end(explode("\r\n", rtrim($response, "\r\n"))); + + if (preg_match('/^(' . $checkCode . ')(.)/', $response, $code)) { + if ($code[2] === '-') { + continue; + } + return $code[1]; + } + throw new SocketException(__d('cake', 'SMTP Error: %s', $response)); + } + } + +} diff --git a/lib/Cake/Network/Http/HttpResponse.php b/lib/Cake/Network/Http/HttpResponse.php index 04322547f..58b74bffc 100644 --- a/lib/Cake/Network/Http/HttpResponse.php +++ b/lib/Cake/Network/Http/HttpResponse.php @@ -350,7 +350,6 @@ class HttpResponse implements ArrayAccess { if ($hex == false) { return $escape; } - $regexChars = ''; foreach ($escape as $key => $char) { $escape[$key] = '\\x' . str_pad(dechex(ord($char)), 2, '0', STR_PAD_LEFT); } diff --git a/lib/Cake/Network/Http/HttpSocket.php b/lib/Cake/Network/Http/HttpSocket.php index 926d70ee6..9cee50af5 100644 --- a/lib/Cake/Network/Http/HttpSocket.php +++ b/lib/Cake/Network/Http/HttpSocket.php @@ -917,7 +917,6 @@ class HttpSocket extends CakeSocket { if ($hex == false) { return $escape; } - $regexChars = ''; foreach ($escape as $key => $char) { $escape[$key] = '\\x' . str_pad(dechex(ord($char)), 2, '0', STR_PAD_LEFT); } diff --git a/lib/Cake/Routing/Dispatcher.php b/lib/Cake/Routing/Dispatcher.php index be0ebe77e..a5d0c10a5 100644 --- a/lib/Cake/Routing/Dispatcher.php +++ b/lib/Cake/Routing/Dispatcher.php @@ -299,7 +299,6 @@ class Dispatcher { include WWW_ROOT . DS . $filters['js']; return true; } - $controller = null; $pathSegments = explode('.', $url); $ext = array_pop($pathSegments); $parts = explode('/', $url); diff --git a/lib/Cake/Routing/Route/CakeRoute.php b/lib/Cake/Routing/Route/CakeRoute.php index c40c84e18..0c66a15bc 100644 --- a/lib/Cake/Routing/Route/CakeRoute.php +++ b/lib/Cake/Routing/Route/CakeRoute.php @@ -399,7 +399,7 @@ class CakeRoute { $greedyNamed = $namedConfig['greedyNamed']; $allowedNamedParams = $namedConfig['rules']; - $named = $pass = $_query = array(); + $named = $pass = array(); foreach ($url as $key => $value) { diff --git a/lib/Cake/Routing/Router.php b/lib/Cake/Routing/Router.php index fd60e2b8e..3f63fd7bb 100644 --- a/lib/Cake/Routing/Router.php +++ b/lib/Cake/Routing/Router.php @@ -487,7 +487,7 @@ class Router { 'named' => array() ); - $r = $ext = null; + $ext = null; if ($url && strpos($url, '/') !== 0) { $url = '/' . $url; @@ -771,7 +771,7 @@ class Router { * @return string Full translated URL with base path. */ public static function url($url = null, $full = false) { - $defaults = $params = array('plugin' => null, 'controller' => null, 'action' => 'index'); + $params = array('plugin' => null, 'controller' => null, 'action' => 'index'); if (is_bool($full)) { $escape = false; @@ -792,7 +792,7 @@ class Router { } $base = $path['base']; - $extension = $output = $mapped = $q = $frag = null; + $extension = $output = $q = $frag = null; if (empty($url)) { $output = isset($path['here']) ? $path['here'] : '/'; diff --git a/lib/Cake/TestSuite/CakeTestCase.php b/lib/Cake/TestSuite/CakeTestCase.php index b769ebdf0..ad5594d81 100644 --- a/lib/Cake/TestSuite/CakeTestCase.php +++ b/lib/Cake/TestSuite/CakeTestCase.php @@ -72,6 +72,7 @@ abstract class CakeTestCase extends PHPUnit_Framework_TestCase { */ protected $_configure = array(); + /** * Runs the test case and collects the results in a TestResult object. * If no TestResult object is passed a new one will be created. diff --git a/lib/Cake/TestSuite/CakeTestLoader.php b/lib/Cake/TestSuite/CakeTestLoader.php index e00b716f4..9fb47278a 100644 --- a/lib/Cake/TestSuite/CakeTestLoader.php +++ b/lib/Cake/TestSuite/CakeTestLoader.php @@ -22,8 +22,8 @@ class CakeTestLoader extends PHPUnit_Runner_StandardTestSuiteLoader { /** * Load a file and find the first test case / suite in that file. * - * @param string $filePath - * @param string $params + * @param string $filePath + * @param string $params * @return ReflectionClass */ public function load($filePath, $params = '') { @@ -45,7 +45,7 @@ class CakeTestLoader extends PHPUnit_Runner_StandardTestSuiteLoader { /** * Generates the base path to a set of tests based on the parameters. * - * @param array $params + * @param array $params * @return string The base path. */ protected static function _basePath($params) { @@ -76,6 +76,7 @@ class CakeTestLoader extends PHPUnit_Runner_StandardTestSuiteLoader { $case = str_replace('Test.php', '', $case); $testCases[$testCaseFile] = $case; } + sort($testCases); return $testCases; } diff --git a/lib/Cake/TestSuite/templates/missing_conenction.php b/lib/Cake/TestSuite/templates/missing_connection.php similarity index 100% rename from lib/Cake/TestSuite/templates/missing_conenction.php rename to lib/Cake/TestSuite/templates/missing_connection.php diff --git a/lib/Cake/Utility/ClassRegistry.php b/lib/Cake/Utility/ClassRegistry.php index f4181f02b..5a523b07f 100644 --- a/lib/Cake/Utility/ClassRegistry.php +++ b/lib/Cake/Utility/ClassRegistry.php @@ -93,7 +93,7 @@ class ClassRegistry { */ public static function &init($class, $type = null) { $_this = ClassRegistry::getInstance(); - $id = $false = false; + $false = false; $true = true; if (!$type) { diff --git a/lib/Cake/Utility/Debugger.php b/lib/Cake/Utility/Debugger.php index 295f11d65..278d7cf24 100644 --- a/lib/Cake/Utility/Debugger.php +++ b/lib/Cake/Utility/Debugger.php @@ -274,7 +274,6 @@ class Debugger { break; } - $helpCode = null; if (!empty($_this->helpPath) && preg_match('/.*\[([0-9]+)\]$/', $description, $codes)) { if (isset($codes[1])) { $helpID = $codes[1]; @@ -418,7 +417,7 @@ class Debugger { * @link http://book.cakephp.org/view/1191/Using-the-Debugger-Class */ public static function excerpt($file, $line, $context = 2) { - $data = $lines = array(); + $lines = array(); if (!file_exists($file)) { return array(); } diff --git a/lib/Cake/Utility/Set.php b/lib/Cake/Utility/Set.php index 839372f19..e1e896b2c 100644 --- a/lib/Cake/Utility/Set.php +++ b/lib/Cake/Utility/Set.php @@ -415,7 +415,6 @@ class Set { $matches[] = $context; continue; } - $match = false; if ($token === '@*' && is_array($context['item'])) { $matches[] = array( 'trace' => array_merge($context['trace'], (array)$key), diff --git a/lib/Cake/Utility/String.php b/lib/Cake/Utility/String.php index 8fc0a2ddf..ce8749056 100644 --- a/lib/Cake/Utility/String.php +++ b/lib/Cake/Utility/String.php @@ -33,7 +33,6 @@ class String { */ public static function uuid() { $node = env('SERVER_ADDR'); - $pid = null; if (strpos($node, ':') !== false) { if (substr_count($node, '::')) { diff --git a/lib/Cake/Utility/Xml.php b/lib/Cake/Utility/Xml.php index ab2f21e42..ca70bb06d 100644 --- a/lib/Cake/Utility/Xml.php +++ b/lib/Cake/Utility/Xml.php @@ -194,7 +194,6 @@ class Xml { $value = ''; } $isNamespace = strpos($key, 'xmlns:'); - $nsUri = null; if ($isNamespace !== false) { $node->setAttributeNS('http://www.w3.org/2000/xmlns/', $key, $value); continue; diff --git a/lib/Cake/View/Helper/FormHelper.php b/lib/Cake/View/Helper/FormHelper.php index 5140257e9..b46f39c11 100644 --- a/lib/Cake/View/Helper/FormHelper.php +++ b/lib/Cake/View/Helper/FormHelper.php @@ -469,8 +469,8 @@ class FormHelper extends AppHelper { * - `class` string The classname for the error message * * @param string $field A field name, like "Modelname.fieldname" - * @param mixed $text Error message or array of $options. If array, `attributes` key - * will get used as html attributes for error container + * @param mixed $text Error message as string or array of messages. + * If array contains `attributes` key it will be used as options for error container * @param array $options Rendering options for
wrapper tag * @return string If there are errors this method returns an error message, otherwise null. * @access public @@ -482,36 +482,63 @@ class FormHelper extends AppHelper { $this->setEntity($field); if ($error = $this->tagIsInvalid()) { - if (is_array($error)) { - list(,,$field) = explode('.', $field); - if (isset($error[$field])) { - $error = $error[$field]; - } else { - return null; - } - } - - if (is_array($text) && is_numeric($error) && $error > 0) { - $error--; - } if (is_array($text)) { - $options = array_merge($options, array_intersect_key($text, $defaults)); if (isset($text['attributes']) && is_array($text['attributes'])) { $options = array_merge($options, $text['attributes']); + unset($text['attributes']); } - $text = isset($text[$error]) ? $text[$error] : null; - unset($options[$error]); + $tmp = array(); + foreach ($error as &$e) { + if (isset($text[$e])) { + $tmp []= $text[$e]; + } else { + $tmp []= $e; + } + } + $text = $tmp; } if ($text != null) { $error = $text; - } elseif (is_numeric($error)) { - $error = __d('cake', 'Error in field %s', Inflector::humanize($this->field())); + } + if (is_array($error)) { + foreach ($error as &$e) { + if (is_numeric($e)) { + $e = __d('cake', 'Error in field %s', Inflector::humanize($this->field())); + } + } } if ($options['escape']) { $error = h($error); unset($options['escape']); } + if (is_array($error)) { + if (count($error) > 1) { + $listParams = array(); + if (isset($options['listOptions'])) { + if (is_string($options['listOptions'])) { + $listParams []= $options['listOptions']; + } else { + if (isset($options['listOptions']['itemOptions'])) { + $listParams []= $options['listOptions']['itemOptions']; + unset($options['listOptions']['itemOptions']); + } else { + $listParams []= array(); + } + if (isset($options['listOptions']['tag'])) { + $listParams []= $options['listOptions']['tag']; + unset($options['listOptions']['tag']); + } + array_unshift($listParams, $options['listOptions']); + } + unset($options['listOptions']); + } + array_unshift($listParams, $error); + $error = call_user_func_array(array($this->Html, 'nestedList'), $listParams); + } else { + $error = array_pop($error); + } + } if ($options['wrap']) { $tag = is_string($options['wrap']) ? $options['wrap'] : 'div'; unset($options['wrap']); @@ -1211,7 +1238,7 @@ class FormHelper extends AppHelper { $this->__secure(null, '' . $options['value']); } - return $this->Html->useTag('hidden', $options['name'], array_diff_key($options, array('name' => '', 'class' => ''))); + return $this->Html->useTag('hidden', $options['name'], array_diff_key($options, array('name' => ''))); } /** diff --git a/lib/Cake/View/elements/email/html/default.ctp b/lib/Cake/View/emails/html/default.ctp similarity index 100% rename from lib/Cake/View/elements/email/html/default.ctp rename to lib/Cake/View/emails/html/default.ctp diff --git a/lib/Cake/View/elements/email/text/default.ctp b/lib/Cake/View/emails/text/default.ctp similarity index 100% rename from lib/Cake/View/elements/email/text/default.ctp rename to lib/Cake/View/emails/text/default.ctp diff --git a/lib/Cake/View/layouts/email/html/default.ctp b/lib/Cake/View/layouts/emails/html/default.ctp similarity index 100% rename from lib/Cake/View/layouts/email/html/default.ctp rename to lib/Cake/View/layouts/emails/html/default.ctp diff --git a/lib/Cake/View/layouts/email/text/default.ctp b/lib/Cake/View/layouts/emails/text/default.ctp similarity index 100% rename from lib/Cake/View/layouts/email/text/default.ctp rename to lib/Cake/View/layouts/emails/text/default.ctp diff --git a/lib/Cake/tests/Case/AllCacheEnginesTest.php b/lib/Cake/tests/Case/AllCacheTest.php similarity index 84% rename from lib/Cake/tests/Case/AllCacheEnginesTest.php rename to lib/Cake/tests/Case/AllCacheTest.php index 29cf33a19..93a640c99 100644 --- a/lib/Cake/tests/Case/AllCacheEnginesTest.php +++ b/lib/Cake/tests/Case/AllCacheTest.php @@ -1,6 +1,6 @@ addTestDirectory(CORE_TEST_CASES . DS . 'Cache'); + $suite->addTestDirectory(CORE_TEST_CASES . DS . 'Cache' . DS . 'Engine'); return $suite; } } diff --git a/lib/Cake/tests/Case/AllConfigureTest.php b/lib/Cake/tests/Case/AllConfigureTest.php index 22c6f216e..da2358b3c 100644 --- a/lib/Cake/tests/Case/AllConfigureTest.php +++ b/lib/Cake/tests/Case/AllConfigureTest.php @@ -20,7 +20,7 @@ /** * AllConfigureTest class * - * This test group will run cache engine tests. + * This test group will run configure tests. * * @package cake.tests.groups */ @@ -32,9 +32,8 @@ class AllConfigureTest extends PHPUnit_Framework_TestSuite { * @return void */ public static function suite() { - $suite = new CakeTestSuite('All Configure and Core related tests'); + $suite = new CakeTestSuite('All Configure related tests'); - $suite->addTestDirectory(CORE_TEST_CASES . DS . 'Core'); $suite->addTestDirectory(CORE_TEST_CASES . DS . 'Configure'); return $suite; } diff --git a/lib/Cake/tests/Case/AllConsoleTest.php b/lib/Cake/tests/Case/AllConsoleTest.php new file mode 100644 index 000000000..a83159d4f --- /dev/null +++ b/lib/Cake/tests/Case/AllConsoleTest.php @@ -0,0 +1,44 @@ +addTestFile($path . 'AllConsoleLibsTest.php'); + $suite->addTestFile($path . 'AllTasksTest.php'); + $suite->addTestFile($path . 'AllShellsTest.php'); + return $suite; + } +} \ No newline at end of file diff --git a/lib/Cake/tests/Case/AllControllersTest.php b/lib/Cake/tests/Case/AllControllerTest.php similarity index 100% rename from lib/Cake/tests/Case/AllControllersTest.php rename to lib/Cake/tests/Case/AllControllerTest.php diff --git a/lib/Cake/tests/Case/AllXmlTest.php b/lib/Cake/tests/Case/AllCoreTest.php similarity index 66% rename from lib/Cake/tests/Case/AllXmlTest.php rename to lib/Cake/tests/Case/AllCoreTest.php index 69f7a0986..e12152d00 100644 --- a/lib/Cake/tests/Case/AllXmlTest.php +++ b/lib/Cake/tests/Case/AllCoreTest.php @@ -1,6 +1,6 @@ addTestFile(CORE_TEST_CASES . DS . 'Utility' . DS . 'XmlTest.php'); - $suite->addTestFile(CORE_TEST_CASES . DS . 'View' . DS . 'Helper' . DS . 'RssHelperTest.php'); + $suite->addTestDirectory(CORE_TEST_CASES . DS . 'Core'); return $suite; } -} \ No newline at end of file +} + diff --git a/lib/Cake/tests/Case/AllErrorTest.php b/lib/Cake/tests/Case/AllErrorTest.php index 4d18079d1..c23b0994f 100644 --- a/lib/Cake/tests/Case/AllErrorTest.php +++ b/lib/Cake/tests/Case/AllErrorTest.php @@ -32,12 +32,11 @@ class AllErrorTest extends PHPUnit_Framework_TestSuite { * @return void */ public static function suite() { - $suite = new PHPUnit_Framework_TestSuite('All Error handling tests'); + $suite = new CakeTestSuite('All Error handling tests'); $libs = CORE_TEST_CASES . DS; - $suite->addTestFile($libs . 'Error' . DS . 'ErrorHandlerTest.php'); - $suite->addTestFile($libs . 'Error' . DS . 'ExceptionRendererTest.php'); + $suite->addTestDirectory($libs . 'Error'); return $suite; } } diff --git a/lib/Cake/tests/Case/AllLocalizationTest.php b/lib/Cake/tests/Case/AllI18nTest.php similarity index 100% rename from lib/Cake/tests/Case/AllLocalizationTest.php rename to lib/Cake/tests/Case/AllI18nTest.php diff --git a/lib/Cake/tests/Case/AllJsHelpersTest.php b/lib/Cake/tests/Case/AllJsHelpersTest.php deleted file mode 100644 index 820291bbb..000000000 --- a/lib/Cake/tests/Case/AllJsHelpersTest.php +++ /dev/null @@ -1,44 +0,0 @@ -addTestFile($helperTestPath . 'JsHelperTest.php'); - $suite->addTestFile($helperTestPath . 'JqueryEngineHelperTest.php'); - $suite->addTestFile($helperTestPath . 'MootoolsEngineHelperTest.php'); - $suite->addTestFile($helperTestPath . 'PrototypeEngineHelperTest.php'); - return $suite; - } -} diff --git a/lib/Cake/tests/Case/AllLogTest.php b/lib/Cake/tests/Case/AllLogTest.php new file mode 100644 index 000000000..d15d0940d --- /dev/null +++ b/lib/Cake/tests/Case/AllLogTest.php @@ -0,0 +1,41 @@ +addTestDirectory(CORE_TEST_CASES . DS . 'Log'); + $suite->addTestDirectory(CORE_TEST_CASES . DS . 'Log' . DS . 'Engine'); + return $suite; + } +} + diff --git a/lib/Cake/tests/Case/AllSocketTest.php b/lib/Cake/tests/Case/AllNetworkTest.php similarity index 78% rename from lib/Cake/tests/Case/AllSocketTest.php rename to lib/Cake/tests/Case/AllNetworkTest.php index 522a129b2..c090c4349 100644 --- a/lib/Cake/tests/Case/AllSocketTest.php +++ b/lib/Cake/tests/Case/AllNetworkTest.php @@ -1,6 +1,6 @@ addTestFile(CORE_TEST_CASES . DS . 'Network' . DS . 'CakeSocketTest.php'); + $suite->addTestDirectory(CORE_TEST_CASES . DS . 'Network'); $suite->addTestDirectory(CORE_TEST_CASES . DS . 'Network' . DS . 'Http'); return $suite; } -} \ No newline at end of file +} diff --git a/lib/Cake/tests/Case/AllRoutingTest.php b/lib/Cake/tests/Case/AllRoutingTest.php index a8e7f0707..a1f1372e7 100644 --- a/lib/Cake/tests/Case/AllRoutingTest.php +++ b/lib/Cake/tests/Case/AllRoutingTest.php @@ -32,13 +32,12 @@ class AllRoutingTest extends PHPUnit_Framework_TestSuite { * @return void */ public static function suite() { - $suite = new CakeTestSuite('All Router and Dispatcher class tests'); + $suite = new CakeTestSuite('All Routing class tests'); $libs = CORE_TEST_CASES . DS; $suite->addTestDirectory($libs . 'Routing'); - $suite->addTestFile($libs . 'Network' . DS . 'CakeResponseTest.php'); - $suite->addTestFile($libs . 'Network' . DS . 'CakeRequestTest.php'); + $suite->addTestDirectory($libs . 'Routing' . DS . 'Route'); return $suite; } } diff --git a/lib/Cake/tests/Case/AllTestsTest.php b/lib/Cake/tests/Case/AllTestsTest.php index a663781b9..30367e0b8 100644 --- a/lib/Cake/tests/Case/AllTestsTest.php +++ b/lib/Cake/tests/Case/AllTestsTest.php @@ -34,25 +34,26 @@ class AllTests extends PHPUnit_Framework_TestSuite { $suite = new PHPUnit_Framework_TestSuite('All Tests'); $path = CORE_TEST_CASES . DS; - $console = $path . 'Console' . DS; - $suite->addTestFile($console . 'AllConsoleTest.php'); + $suite->addTestFile($path . 'BasicsTest.php'); + $suite->addTestFile($path . 'AllConsoleTest.php'); $suite->addTestFile($path . 'AllBehaviorsTest.php'); - $suite->addTestFile($path . 'AllCacheEnginesTest.php'); + $suite->addTestFile($path . 'AllCacheTest.php'); $suite->addTestFile($path . 'AllComponentsTest.php'); $suite->addTestFile($path . 'AllConfigureTest.php'); - $suite->addTestFile($path . 'AllControllersTest.php'); + $suite->addTestFile($path . 'AllCoreTest.php'); + $suite->addTestFile($path . 'AllControllerTest.php'); $suite->addTestFile($path . 'AllDatabaseTest.php'); $suite->addTestFile($path . 'AllErrorTest.php'); $suite->addTestFile($path . 'AllHelpersTest.php'); - $suite->addTestFile($path . 'AllLibsTest.php'); - $suite->addTestFile($path . 'AllLocalizationTest.php'); + $suite->addTestFile($path . 'AllLogTest.php'); + $suite->addTestFile($path . 'AllI18nTest.php'); $suite->addTestFile($path . 'AllModelTest.php'); $suite->addTestFile($path . 'AllRoutingTest.php'); - $suite->addTestFile($path . 'AllSocketTest.php'); + $suite->addTestFile($path . 'AllNetworkTest.php'); $suite->addTestFile($path . 'AllTestSuiteTest.php');; - $suite->addTestFile($path . 'AllViewsTest.php'); - $suite->addTestFile($path . 'AllXmlTest.php'); + $suite->addTestFile($path . 'AllUtilityTest.php'); + $suite->addTestFile($path . 'AllViewTest.php'); return $suite; } } diff --git a/lib/Cake/tests/Case/AllLibsTest.php b/lib/Cake/tests/Case/AllUtilityTest.php similarity index 64% rename from lib/Cake/tests/Case/AllLibsTest.php rename to lib/Cake/tests/Case/AllUtilityTest.php index 73a331385..1b2882430 100644 --- a/lib/Cake/tests/Case/AllLibsTest.php +++ b/lib/Cake/tests/Case/AllUtilityTest.php @@ -1,6 +1,6 @@ addTestFile(CORE_TEST_CASES . DS . 'BasicsTest.php'); + $suite = new CakeTestSuite('All Utility class tests'); $suite->addTestDirectory(CORE_TEST_CASES . DS . 'Utility'); - $suite->addTestDirectory(CORE_TEST_CASES . DS . 'Log'); - $suite->addTestFile(CORE_TEST_CASES . DS . 'Model' . DS . 'Datasource' . DS . 'CakeSessionTest.php'); - //$suite->addTestDirectory(CORE_TEST_CASES . DS . 'Model' . DS . 'Datasource' . DS . 'Session'); return $suite; } -} \ No newline at end of file +} diff --git a/lib/Cake/tests/Case/AllViewsTest.php b/lib/Cake/tests/Case/AllViewTest.php similarity index 90% rename from lib/Cake/tests/Case/AllViewsTest.php rename to lib/Cake/tests/Case/AllViewTest.php index 46a094625..9ccb6cece 100644 --- a/lib/Cake/tests/Case/AllViewsTest.php +++ b/lib/Cake/tests/Case/AllViewTest.php @@ -1,6 +1,6 @@ addTestFile($path . 'AllShellsTest.php'); return $suite; } -} \ No newline at end of file +} diff --git a/lib/Cake/tests/Case/Console/Command/ShellTest.php b/lib/Cake/tests/Case/Console/Command/ShellTest.php index fbbab30b1..94208bf79 100644 --- a/lib/Cake/tests/Case/Console/Command/ShellTest.php +++ b/lib/Cake/tests/Case/Console/Command/ShellTest.php @@ -170,20 +170,20 @@ class ShellTest extends CakeTestCase { public function testInitialize() { App::build(array( 'plugins' => array(LIBS . 'tests' . DS . 'test_app' . DS . 'plugins' . DS), - 'models' => array(LIBS . 'tests' . DS . 'test_app' . DS . 'models' . DS) + 'models' => array(LIBS . 'tests' . DS . 'test_app' . DS . 'Model' . DS) ), true); $this->Shell->uses = array('TestPlugin.TestPluginPost'); $this->Shell->initialize(); $this->assertTrue(isset($this->Shell->TestPluginPost)); - $this->assertIsA($this->Shell->TestPluginPost, 'TestPluginPost'); + $this->assertInstanceOf('TestPluginPost', $this->Shell->TestPluginPost); $this->assertEqual($this->Shell->modelClass, 'TestPluginPost'); $this->Shell->uses = array('Comment'); $this->Shell->initialize(); $this->assertTrue(isset($this->Shell->Comment)); - $this->assertIsA($this->Shell->Comment, 'Comment'); + $this->assertInstanceOf('Comment', $this->Shell->Comment); $this->assertEqual($this->Shell->modelClass, 'Comment'); App::build(); diff --git a/lib/Cake/tests/Case/Console/Command/Task/ControllerTaskTest.php b/lib/Cake/tests/Case/Console/Command/Task/ControllerTaskTest.php index a34b44397..4cfac5688 100644 --- a/lib/Cake/tests/Case/Console/Command/Task/ControllerTaskTest.php +++ b/lib/Cake/tests/Case/Console/Command/Task/ControllerTaskTest.php @@ -94,6 +94,7 @@ class ControllerTaskTest extends CakeTestCase { public function teardown() { unset($this->Task); ClassRegistry::flush(); + App::build(); } /** diff --git a/lib/Cake/tests/Case/Console/Command/Task/PluginTaskTest.php b/lib/Cake/tests/Case/Console/Command/Task/PluginTaskTest.php index a46465857..97452cc09 100644 --- a/lib/Cake/tests/Case/Console/Command/Task/PluginTaskTest.php +++ b/lib/Cake/tests/Case/Console/Command/Task/PluginTaskTest.php @@ -67,11 +67,11 @@ class PluginTaskTest extends CakeTestCase { $path = $this->Task->path . 'bake_test_plugin'; - $file = $path . DS . 'bake_test_plugin_app_controller.php'; + $file = $path . DS . 'Controller' . DS .'BakeTestPluginAppController.php'; $this->Task->expects($this->at(2))->method('createFile') ->with($file, new PHPUnit_Framework_Constraint_IsAnything()); - $file = $path . DS . 'bake_test_plugin_app_model.php'; + $file = $path . DS . 'Model' . DS . 'BakeTestPluginAppModel.php'; $this->Task->expects($this->at(3))->method('createFile') ->with($file, new PHPUnit_Framework_Constraint_IsAnything()); @@ -82,19 +82,16 @@ class PluginTaskTest extends CakeTestCase { $directories = array( 'config' . DS . 'schema', - 'models' . DS . 'behaviors', - 'models' . DS . 'datasources', - 'console' . DS . 'shells' . DS . 'tasks', - 'controllers' . DS . 'components', - 'libs', - 'views' . DS . 'helpers', - 'tests' . DS . 'cases' . DS . 'components', - 'tests' . DS . 'cases' . DS . 'helpers', - 'tests' . DS . 'cases' . DS . 'behaviors', - 'tests' . DS . 'cases' . DS . 'controllers', - 'tests' . DS . 'cases' . DS . 'models', - 'tests' . DS . 'groups', - 'tests' . DS . 'fixtures', + 'Model' . DS . 'Behavior', + 'Model' . DS . 'Datasource', + 'Console' . DS . 'Command' . DS . 'Task', + 'Controller' . DS . 'Component', + 'Lib', + 'View' . DS . 'Helper', + 'tests' . DS . 'Case' . DS . 'Controller' . DS . 'Component', + 'tests' . DS . 'Case' . DS . 'View' . DS . 'Helper', + 'tests' . DS . 'Case' . DS . 'Model' . DS . 'Behavior', + 'tests' . DS . 'Fixture', 'vendors', 'webroot' ); @@ -117,11 +114,11 @@ class PluginTaskTest extends CakeTestCase { $this->Task->expects($this->at(2))->method('in')->will($this->returnValue('y')); $path = $this->Task->path . 'test_plugin'; - $file = $path . DS . 'test_plugin_app_controller.php'; + $file = $path . DS . 'Controller' . DS . 'TestPluginAppController.php'; $this->Task->expects($this->at(3))->method('createFile') ->with($file, new PHPUnit_Framework_Constraint_IsAnything()); - $file = $path . DS . 'test_plugin_app_model.php'; + $file = $path . DS . 'Model' . DS . 'TestPluginAppModel.php'; $this->Task->expects($this->at(4))->method('createFile') ->with($file, new PHPUnit_Framework_Constraint_IsAnything()); @@ -144,12 +141,12 @@ class PluginTaskTest extends CakeTestCase { ->will($this->returnValue('y')); $path = $this->Task->path . 'bake_test_plugin'; - $file = $path . DS . 'bake_test_plugin_app_controller.php'; + $file = $path . DS . 'Controller' . DS . 'BakeTestPluginAppController.php'; $this->Task->expects($this->at(2))->method('createFile') ->with($file, new PHPUnit_Framework_Constraint_IsAnything()); $path = $this->Task->path . 'bake_test_plugin'; - $file = $path . DS . 'bake_test_plugin_app_model.php'; + $file = $path . DS . 'Model' . DS . 'BakeTestPluginAppModel.php'; $this->Task->expects($this->at(3))->method('createFile') ->with($file, new PHPUnit_Framework_Constraint_IsAnything()); diff --git a/lib/Cake/tests/Case/Controller/Component/CookieComponentTest.php b/lib/Cake/tests/Case/Controller/Component/CookieComponentTest.php index 9254ef94c..dd07e923c 100644 --- a/lib/Cake/tests/Case/Controller/Component/CookieComponentTest.php +++ b/lib/Cake/tests/Case/Controller/Component/CookieComponentTest.php @@ -238,6 +238,19 @@ class CookieComponentTest extends CakeTestCase { $this->Cookie->delete('tag'); } +/** + * test writing values that are not scalars + * + * @return void + */ + function testWriteArrayValues() { + $this->Cookie->secure = false; + $this->Cookie->expects($this->once())->method('_setcookie') + ->with('CakeTestCookie[Testing]', '[1,2,3]', time() + 10, '/', '', false, false); + + $this->Cookie->write('Testing', array(1, 2, 3), false); + } + /** * testReadingCookieValue * @@ -359,7 +372,6 @@ class CookieComponentTest extends CakeTestCase { * @return void */ function testReadingCookieDataOnStartup() { - $data = $this->Cookie->read('Encrytped_array'); $this->assertNull($data); @@ -378,28 +390,29 @@ class CookieComponentTest extends CakeTestCase { 'name' => $this->__encrypt('CakePHP'), 'version' => $this->__encrypt('1.2.0.x'), 'tag' => $this->__encrypt('CakePHP Rocks!')), - 'Plain_array' => 'name|CakePHP,version|1.2.0.x,tag|CakePHP Rocks!', + 'Plain_array' => '{"name":"CakePHP","version":"1.2.0.x","tag":"CakePHP Rocks!"}', 'Plain_multi_cookies' => array( 'name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!')); + $this->Cookie->startup(null); $data = $this->Cookie->read('Encrytped_array'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $data = $this->Cookie->read('Encrytped_multi_cookies'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_array'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_multi_cookies'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $this->Cookie->destroy(); unset($_COOKIE['CakeTestCookie']); } @@ -413,19 +426,19 @@ class CookieComponentTest extends CakeTestCase { function testReadingCookieDataWithoutStartup() { $data = $this->Cookie->read('Encrytped_array'); $expected = null; - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $data = $this->Cookie->read('Encrytped_multi_cookies'); $expected = null; - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_array'); $expected = null; - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_multi_cookies'); $expected = null; - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $_COOKIE['CakeTestCookie'] = array( 'Encrytped_array' => $this->__encrypt(array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!')), @@ -433,7 +446,7 @@ class CookieComponentTest extends CakeTestCase { 'name' => $this->__encrypt('CakePHP'), 'version' => $this->__encrypt('1.2.0.x'), 'tag' => $this->__encrypt('CakePHP Rocks!')), - 'Plain_array' => 'name|CakePHP,version|1.2.0.x,tag|CakePHP Rocks!', + 'Plain_array' => '{"name":"CakePHP","version":"1.2.0.x","tag":"CakePHP Rocks!"}', 'Plain_multi_cookies' => array( 'name' => 'CakePHP', 'version' => '1.2.0.x', @@ -441,23 +454,36 @@ class CookieComponentTest extends CakeTestCase { $data = $this->Cookie->read('Encrytped_array'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $data = $this->Cookie->read('Encrytped_multi_cookies'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_array'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_multi_cookies'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $this->Cookie->destroy(); unset($_COOKIE['CakeTestCookie']); } +/** + * Test Reading legacy cookie values. + * + * @return void + */ + function testReadLegacyCookieValue() { + $_COOKIE['CakeTestCookie'] = array( + 'Legacy' => array('value' => $this->_oldImplode(array(1, 2, 3))) + ); + $result = $this->Cookie->read('Legacy.value'); + $expected = array(1, 2, 3); + $this->assertEquals($expected, $result); + } /** * test that no error is issued for non array data. @@ -470,6 +496,29 @@ class CookieComponentTest extends CakeTestCase { $this->assertNull($this->Cookie->read('value')); } + +/** + * Helper method for generating old style encoded cookie values. + * + * @return string. + */ + protected function _oldImplode(array $array) { + $string = ''; + foreach ($array as $key => $value) { + $string .= ',' . $key . '|' . $value; + } + return substr($string, 1); + } + +/** + * Implode method to keep keys are multidimensional arrays + * + * @param array $array Map of key and values + * @return string String in the form key1|value1,key2|value2 + */ + protected function _implode(array $array) { + return json_encode($array); + } /** * encrypt method @@ -480,23 +529,9 @@ class CookieComponentTest extends CakeTestCase { */ function __encrypt($value) { if (is_array($value)) { - $value = $this->__implode($value); + $value = $this->_implode($value); } return "Q2FrZQ==." . base64_encode(Security::cipher($value, $this->Cookie->key)); } -/** - * implode method - * - * @param array $value - * @return string - * @access private - */ - function __implode($array) { - $string = ''; - foreach ($array as $key => $value) { - $string .= ',' . $key . '|' . $value; - } - return substr($string, 1); - } } diff --git a/lib/Cake/tests/Case/Controller/Component/EmailComponentTest.php b/lib/Cake/tests/Case/Controller/Component/EmailComponentTest.php index 949daf8c2..b70c46511 100644 --- a/lib/Cake/tests/Case/Controller/Component/EmailComponentTest.php +++ b/lib/Cake/tests/Case/Controller/Component/EmailComponentTest.php @@ -20,7 +20,7 @@ */ App::uses('Controller', 'Controller'); App::uses('EmailComponent', 'Controller/Component'); -App::uses('CakeSocket', 'Network'); +App::uses('AbstractTransport', 'Network/Email'); /** * EmailTestComponent class @@ -29,131 +29,6 @@ App::uses('CakeSocket', 'Network'); */ class EmailTestComponent extends EmailComponent { - var $smtpSend = ''; -/** - * smtpSend method override for testing - * - * @access public - * @return mixed - */ - function smtpSend($data, $code = '250') { - return parent::_smtpSend($data, $code); - } - -/** - * undocumented function - * - * @return void - */ - function _smtpSend($data, $code = '250') { - if ($this->_debug) { - $this->smtpSend .= $data . "\n"; - return true; - } - return parent::_smtpSend($data, $code); - } - -/** - * Convenience setter method for testing. - * - * @access public - * @return void - */ - function setConnectionSocket($socket) { - $this->_smtpConnection = $socket; - } - -/** - * Allows mocks to be used with tests. - * - * @param array $config - * @return void - */ - function _getSocket($config) { - if (empty($this->_smtpConnection)) { - parent::_getSocket($config); - } - } - -/** - * Convenience getter method for testing. - * - * @access public - * @return mixed - */ - function getConnectionSocket() { - return $this->_smtpConnection; - } - -/** - * Convenience setter for testing. - * - * @access public - * @return void - */ - function setHeaders($headers) { - $this->_header += $headers; - } - -/** - * Convenience getter for testing. - * - * @access public - * @return array - */ - function getHeaders() { - if (empty($this->_header)) { - return array(); - } - return $this->_header; - } - -/** - * Convenience setter for testing. - * - * @access public - * @return void - */ - function setBoundary() { - $this->_createBoundary(); - } - -/** - * Convenience getter for testing. - * - * @access public - * @return string - */ - function getBoundary() { - if (empty($this->_boundary)) { - return null; - } - return $this->_boundary; - } - -/** - * Convenience getter for testing. - * - * @access public - * @return string - */ - function getMessage() { - if (empty($this->_message)) { - return array(); - } - return $this->_message; - } - -/** - * Convenience getter for testing. - * - * @access protected - * @return string - */ - function _getMessage() { - return $this->_message; - } - /** * Convenience method for testing. * @@ -164,14 +39,49 @@ class EmailTestComponent extends EmailComponent { return parent::_strip($content, $message); } +} + /** - * Wrapper for testing. + * DebugCompTransport class * - * @return void + * @package cake.tests.cases.libs.controller.components */ - function formatAddress($string, $smtp = false) { - return parent::_formatAddress($string, $smtp); +class DebugCompTransport extends AbstractTransport { + +/** + * Last email + * + * @var string + */ + public static $lastEmail = null; + +/** + * Send mail + * + * @params object $email CakeEmail + * @return boolean + */ + public function send(CakeEmail $email) { + $headers = $email->getHeaders(array_fill_keys(array('from', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'bcc', 'subject'), true)); + $to = $headers['To']; + $subject = $headers['Subject']; + unset($headers['To'], $headers['Subject']); + + $message = implode("\n", $email->message()); + + $last = '
';
+		$last .= sprintf("%s %s\n", 'To:', $to);
+		$last .= sprintf("%s %s\n", 'From:', $headers['From']);
+		$last .= sprintf("%s %s\n", 'Subject:', $subject);
+		$last .= sprintf("%s\n\n%s", 'Header:', $this->_headersToString($headers, "\n"));
+		$last .= sprintf("%s\n\n%s", 'Message:', $message);
+		$last .= '
'; + + self::$lastEmail = $last; + + return true; } + } /** @@ -205,13 +115,6 @@ class EmailTestController extends Controller { */ public $components = array('Session', 'EmailTest'); -/** - * pageTitle property - * - * @var string - * @access public - */ - public $pageTitle = 'EmailTest'; } /** @@ -252,7 +155,6 @@ class EmailComponentTest extends CakeTestCase { $this->Controller->Components->init($this->Controller); $this->Controller->EmailTest->initialize($this->Controller, array()); - ClassRegistry::addObject('view', new View($this->Controller)); App::build(array( 'View' => array(LIBS . 'tests' . DS . 'test_app' . DS . 'View'. DS) @@ -268,7 +170,6 @@ class EmailComponentTest extends CakeTestCase { function tearDown() { Configure::write('App.encoding', $this->_appEncoding); App::build(); - $this->Controller->Session->delete('Message'); ClassRegistry::flush(); } @@ -283,252 +184,6 @@ class EmailComponentTest extends CakeTestCase { return str_replace(array("\r\n", "\r"), "\n", $string); } -/** - * testSmtpConfig method - * - * @access public - * @return void - */ - function testSmtpConfig() { - if ($this->skipIf(!@fsockopen('localhost', 25, $err, $errstr, .01), '%s No SMTP server running on localhost')) { - return; - } - $this->Controller->EmailTest->delivery = 'smtp'; - $this->Controller->EmailTest->smtpOptions = array(); - $this->Controller->EmailTest->send('anything'); - $config = array( - 'host' => 'localhost', - 'port' => 25, - 'protocol' => 'smtp', - 'timeout' => 30 - ); - $this->assertEqual($config, $this->Controller->EmailTest->smtpOptions); - - $this->Controller->EmailTest->smtpOptions = array('port' => 80); - $this->Controller->EmailTest->send('anything'); - $config['port'] = 80; - $this->assertEqual($config, $this->Controller->EmailTest->smtpOptions); - } - -/** - * testBadSmtpSend method - * - * @access public - * @return void - */ - function testBadSmtpSend() { - if ($this->skipIf(!@fsockopen('localhost', 25, $err, $errstr, .01), '%s No SMTP server running on localhost')) { - return; - } - $this->Controller->EmailTest->smtpOptions['host'] = 'blah'; - $this->Controller->EmailTest->delivery = 'smtp'; - $this->assertFalse($this->Controller->EmailTest->send('Should not work')); - } - -/** - * testSmtpSend method - * - * @access public - * @return void - */ - function testSmtpSend() { - if ($this->skipIf(!@fsockopen('localhost', 25, $err, $errstr, .01), '%s No SMTP server running on localhost')) { - return; - } - - $this->Controller->EmailTest->to = 'postmaster@localhost'; - $this->Controller->EmailTest->from = 'noreply@example.com'; - $this->Controller->EmailTest->subject = 'Cake SMTP test'; - $this->Controller->EmailTest->replyTo = 'noreply@example.com'; - $this->Controller->EmailTest->template = null; - - $this->Controller->EmailTest->delivery = 'smtp'; - $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); - - $this->Controller->EmailTest->_debug = true; - $this->Controller->EmailTest->sendAs = 'text'; - $expect = <<Host: localhost -Port: 25 -Timeout: 30 -To: postmaster@localhost -From: noreply@example.com -Subject: Cake SMTP test -Header: - -To: postmaster@localhost -From: noreply@example.com -Reply-To: noreply@example.com -Subject: Cake SMTP test -X-Mailer: CakePHP Email Component -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 7bitParameters: - -Message: - -This is the body of the message - - -TEMPDOC; - $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); - $this->assertEqual($this->Controller->Session->read('Message.email.message'), $this->__osFix($expect)); - } - -/** - * testSmtpEhlo method - * - * @access public - * @return void - */ - function testSmtpEhlo() { - if ($this->skipIf(!@fsockopen('localhost', 25, $err, $errstr, .01), '%s No SMTP server running on localhost')) { - return; - } - - $connection = new CakeSocket(array('protocol'=>'smtp', 'host' => 'localhost', 'port' => 25)); - $this->Controller->EmailTest->setConnectionSocket($connection); - $this->Controller->EmailTest->smtpOptions['timeout'] = 10; - $this->assertTrue($connection->connect()); - $this->assertTrue($this->Controller->EmailTest->smtpSend(null, '220') !== false); - $this->skipIf($this->Controller->EmailTest->smtpSend('EHLO locahost', '250') === false, '%s do not support EHLO.'); - $connection->disconnect(); - - $this->Controller->EmailTest->to = 'postmaster@localhost'; - $this->Controller->EmailTest->from = 'noreply@example.com'; - $this->Controller->EmailTest->subject = 'Cake SMTP test'; - $this->Controller->EmailTest->replyTo = 'noreply@example.com'; - $this->Controller->EmailTest->template = null; - - $this->Controller->EmailTest->delivery = 'smtp'; - $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); - - $this->Controller->EmailTest->_debug = true; - $this->Controller->EmailTest->sendAs = 'text'; - $expect = <<Host: localhost -Port: 25 -Timeout: 30 -To: postmaster@localhost -From: noreply@example.com -Subject: Cake SMTP test -Header: - -To: postmaster@localhost -From: noreply@example.com -Reply-To: noreply@example.com -Subject: Cake SMTP test -X-Mailer: CakePHP Email Component -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 7bitParameters: - -Message: - -This is the body of the message - - -TEMPDOC; - $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); - $this->assertEqual($this->Controller->Session->read('Message.email.message'), $this->__osFix($expect)); - } - -/** - * testSmtpSendMultipleTo method - * - * @access public - * @return void - */ - function testSmtpSendMultipleTo() { - if ($this->skipIf(!@fsockopen('localhost', 25), '%s No SMTP server running on localhost')) { - return; - } - $this->Controller->EmailTest->reset(); - $this->Controller->EmailTest->to = array('postmaster@localhost', 'root@localhost'); - $this->Controller->EmailTest->from = 'noreply@example.com'; - $this->Controller->EmailTest->subject = 'Cake SMTP multiple To test'; - $this->Controller->EmailTest->replyTo = 'noreply@example.com'; - $this->Controller->EmailTest->template = null; - $this->Controller->EmailTest->_debug = true; - $this->Controller->EmailTest->sendAs = 'text'; - $this->Controller->EmailTest->delivery = 'smtp'; - - $socket = $this->getMock('CakeSocket'); - $socket->expects($this->any()) - ->method('connect') - ->will($this->returnValue(true)); - $this->Controller->EmailTest->setConnectionSocket($socket); - - $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); - - $this->assertPattern('/EHLO localhost\n/', $this->Controller->EmailTest->smtpSend); - $this->assertPattern('/MAIL FROM: \n/', $this->Controller->EmailTest->smtpSend); - $this->assertPattern('/RCPT TO: \n/', $this->Controller->EmailTest->smtpSend); - $this->assertPattern('/RCPT TO: \n/', $this->Controller->EmailTest->smtpSend); - $this->assertPattern( - '/To: postmaster@localhost, root@localhost[\n\r]/', - $this->Controller->EmailTest->smtpSend - ); - } - -/** - * test sending smtp from a host using a port. - * - * @return void - */ - function testSmtpSendHostWithPort() { - $bkp = env('HTTP_HOST'); - $_SERVER['HTTP_HOST'] = 'localhost:8080'; - - $this->Controller->EmailTest->reset(); - $this->Controller->EmailTest->to = array('root@localhost'); - $this->Controller->EmailTest->from = 'noreply@example.com'; - $this->Controller->EmailTest->subject = 'Cake SMTP host test'; - $this->Controller->EmailTest->replyTo = 'noreply@example.com'; - $this->Controller->EmailTest->template = null; - $this->Controller->EmailTest->delivery = 'smtp'; - $this->Controller->EmailTest->sendAs = 'text'; - $this->Controller->EmailTest->_debug = true; - - $socket = $this->getMock('CakeSocket'); - $socket->expects($this->any()) - ->method('connect') - ->will($this->returnValue(true)); - - $this->Controller->EmailTest->setConnectionSocket($socket); - $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); - - $this->assertPattern('/EHLO localhost\n/', $this->Controller->EmailTest->smtpSend); - - $_SERVER['HTTP_HOST'] = $bkp; - } - -/** - * testAuthenticatedSmtpSend method - * - * @access public - * @return void - */ - function testAuthenticatedSmtpSend() { - if ($this->skipIf(!@fsockopen('localhost', 25, $err, $errstr, .01), '%s No SMTP server running on localhost')) { - return; - } - - $this->Controller->EmailTest->to = 'postmaster@localhost'; - $this->Controller->EmailTest->from = 'noreply@example.com'; - $this->Controller->EmailTest->subject = 'Cake SMTP test'; - $this->Controller->EmailTest->replyTo = 'noreply@example.com'; - $this->Controller->EmailTest->template = null; - $this->Controller->EmailTest->smtpOptions['username'] = 'test'; - $this->Controller->EmailTest->smtpOptions['password'] = 'testing'; - - $this->Controller->EmailTest->delivery = 'smtp'; - $result = $this->Controller->EmailTest->send('This is the body of the message'); - $code = substr($this->Controller->EmailTest->smtpError, 0, 3); - $this->skipIf(!$code, '%s Authentication not enabled on server'); - - $this->assertFalse($result); - $this->assertEqual($code, '535'); - } - /** * testSendFormats method * @@ -536,50 +191,49 @@ TEMPDOC; * @return void */ function testSendFormats() { - $this->Controller->EmailTest->to = 'postmaster@localhost'; + $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Cake SMTP test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->template = null; - $this->Controller->EmailTest->delivery = 'debug'; + $this->Controller->EmailTest->delivery = 'DebugComp'; $this->Controller->EmailTest->messageId = false; $date = date(DATE_RFC2822); $message = <<To: postmaster@localhost +
To: postmaster@example.com
 From: noreply@example.com
 Subject: Cake SMTP test
 Header:
 
 From: noreply@example.com
 Reply-To: noreply@example.com
-Date: $date
 X-Mailer: CakePHP Email Component
+Date: $date
+MIME-Version: 1.0
 Content-Type: {CONTENTTYPE}
-Content-Transfer-Encoding: 7bitParameters:
-
-Message:
+Content-Transfer-Encoding: 7bitMessage:
 
 This is the body of the message
 
 
MSGBLOC; + $this->Controller->EmailTest->sendAs = 'text'; $expect = str_replace('{CONTENTTYPE}', 'text/plain; charset=UTF-8', $message); $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); - $this->assertEqual($this->Controller->Session->read('Message.email.message'), $this->__osFix($expect)); + $this->assertEqual(DebugCompTransport::$lastEmail, $this->__osFix($expect)); $this->Controller->EmailTest->sendAs = 'html'; $expect = str_replace('{CONTENTTYPE}', 'text/html; charset=UTF-8', $message); $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); - $this->assertEqual($this->Controller->Session->read('Message.email.message'), $this->__osFix($expect)); + $this->assertEqual(DebugCompTransport::$lastEmail, $this->__osFix($expect)); // TODO: better test for format of message sent? $this->Controller->EmailTest->sendAs = 'both'; $expect = str_replace('{CONTENTTYPE}', 'multipart/alternative; boundary="alt-"', $message); - $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); - $this->assertEqual($this->Controller->Session->read('Message.email.message'), $this->__osFix($expect)); + $this->assertEqual(preg_replace('/alt-[a-z0-9]{32}/i', 'alt-', DebugCompTransport::$lastEmail), $this->__osFix($expect)); } /** @@ -591,35 +245,35 @@ MSGBLOC; function testTemplates() { ClassRegistry::flush(); - $this->Controller->EmailTest->to = 'postmaster@localhost'; + $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Cake SMTP test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; - $this->Controller->EmailTest->delivery = 'debug'; + $this->Controller->EmailTest->delivery = 'DebugComp'; $this->Controller->EmailTest->messageId = false; $date = date(DATE_RFC2822); $header = <<Controller->EmailTest->layout = 'default'; $this->Controller->EmailTest->template = 'default'; + $this->Controller->set('title_for_layout', 'Email Test'); $text = <<Controller->EmailTest->sendAs = 'text'; $expect = '
' . str_replace('{CONTENTTYPE}', 'text/plain; charset=UTF-8', $header) . $text . "\n" . '
'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); - $this->assertEqual($this->Controller->Session->read('Message.email.message'), $this->__osFix($expect)); + $this->assertEqual(DebugCompTransport::$lastEmail, $this->__osFix($expect)); $this->Controller->EmailTest->sendAs = 'html'; $expect = '
' . str_replace('{CONTENTTYPE}', 'text/html; charset=UTF-8', $header) . $html . "\n" . '
'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); - $this->assertEqual($this->Controller->Session->read('Message.email.message'), $this->__osFix($expect)); + $this->assertEqual(DebugCompTransport::$lastEmail, $this->__osFix($expect)); $this->Controller->EmailTest->sendAs = 'both'; $expect = str_replace('{CONTENTTYPE}', 'multipart/alternative; boundary="alt-"', $header); @@ -660,7 +314,7 @@ HTMLBLOC; $expect = '
' . $expect . '--alt---' . "\n\n" . '
'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); - $this->assertEqual($this->Controller->Session->read('Message.email.message'), $this->__osFix($expect)); + $this->assertEqual(preg_replace('/alt-[a-z0-9]{32}/i', 'alt-', DebugCompTransport::$lastEmail), $this->__osFix($expect)); $html = << @@ -681,10 +335,7 @@ HTMLBLOC; $this->Controller->EmailTest->sendAs = 'html'; $expect = '
' . str_replace('{CONTENTTYPE}', 'text/html; charset=UTF-8', $header) . $html . '
'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message', 'default', 'thin')); - $this->assertEqual($this->Controller->Session->read('Message.email.message'), $this->__osFix($expect)); - - $result = ClassRegistry::getObject('view'); - $this->assertFalse($result); + $this->assertEqual(DebugCompTransport::$lastEmail, $this->__osFix($expect)); } /** @@ -693,12 +344,12 @@ HTMLBLOC; * @return void */ function testTemplateNestedElements() { - $this->Controller->EmailTest->to = 'postmaster@localhost'; + $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Cake SMTP test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; - $this->Controller->EmailTest->delivery = 'debug'; + $this->Controller->EmailTest->delivery = 'DebugComp'; $this->Controller->EmailTest->messageId = false; $this->Controller->EmailTest->layout = 'default'; $this->Controller->EmailTest->template = 'nested_element'; @@ -706,36 +357,11 @@ HTMLBLOC; $this->Controller->helpers = array('Html'); $this->Controller->EmailTest->send(); - $result = $this->Controller->Session->read('Message.email.message'); + $result = DebugCompTransport::$lastEmail; $this->assertPattern('/Test/', $result); $this->assertPattern('/http\:\/\/example\.com/', $result); } -/** - * testSmtpSendSocket method - * - * @access public - * @return void - */ - function testSmtpSendSocket() { - if ($this->skipIf(!@fsockopen('localhost', 25, $err, $errstr, .01), '%s No SMTP server running on localhost')) { - return; - } - - $socket = new CakeSocket(array_merge(array('protocol'=>'smtp'), $this->Controller->EmailTest->smtpOptions)); - $this->Controller->EmailTest->setConnectionSocket($socket); - - $this->assertSame($this->Controller->EmailTest->getConnectionSocket(), $socket); - - $response = $this->Controller->EmailTest->smtpSend('HELO', '250'); - $this->assertPattern('/501 Syntax: HELO hostname/', $this->Controller->EmailTest->smtpError); - - $this->Controller->EmailTest->reset(); - $response = $this->Controller->EmailTest->smtpSend('HELO somehostname', '250'); - - $this->assertNoPattern('/501 Syntax: HELO hostname/', (string)$this->Controller->EmailTest->smtpError); - } - /** * testSendDebug method * @@ -743,7 +369,7 @@ HTMLBLOC; * @return void */ function testSendDebug() { - $this->Controller->EmailTest->to = 'postmaster@localhost'; + $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->cc = 'cc@example.com'; $this->Controller->EmailTest->bcc = 'bcc@example.com'; @@ -751,11 +377,11 @@ HTMLBLOC; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->template = null; - $this->Controller->EmailTest->delivery = 'debug'; + $this->Controller->EmailTest->delivery = 'DebugComp'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); - $result = $this->Controller->Session->read('Message.email.message'); + $result = DebugCompTransport::$lastEmail; - $this->assertPattern('/To: postmaster@localhost\n/', $result); + $this->assertPattern('/To: postmaster@example.com\n/', $result); $this->assertPattern('/Subject: Cake Debug Test\n/', $result); $this->assertPattern('/Reply-To: noreply@example.com\n/', $result); $this->assertPattern('/From: noreply@example.com\n/', $result); @@ -764,7 +390,7 @@ HTMLBLOC; $this->assertPattern('/Date: ' . preg_quote(date(DATE_RFC2822)) . '\n/', $result); $this->assertPattern('/X-Mailer: CakePHP Email Component\n/', $result); $this->assertPattern('/Content-Type: text\/plain; charset=UTF-8\n/', $result); - $this->assertPattern('/Content-Transfer-Encoding: 7bitParameters:\n/', $result); + $this->assertPattern('/Content-Transfer-Encoding: 7bitMessage:\n/', $result); $this->assertPattern('/This is the body of the message/', $result); } @@ -776,23 +402,24 @@ HTMLBLOC; function testSendDebugWithNoSessions() { $session = $this->Controller->Session; unset($this->Controller->Session); - $this->Controller->EmailTest->to = 'postmaster@localhost'; + $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Cake Debug Test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->template = null; - $this->Controller->EmailTest->delivery = 'debug'; - $result = $this->Controller->EmailTest->send('This is the body of the message'); + $this->Controller->EmailTest->delivery = 'DebugComp'; + $this->Controller->EmailTest->send('This is the body of the message'); + $result = DebugCompTransport::$lastEmail; - $this->assertPattern('/To: postmaster@localhost\n/', $result); + $this->assertPattern('/To: postmaster@example.com\n/', $result); $this->assertPattern('/Subject: Cake Debug Test\n/', $result); $this->assertPattern('/Reply-To: noreply@example.com\n/', $result); $this->assertPattern('/From: noreply@example.com\n/', $result); $this->assertPattern('/Date: ' . preg_quote(date(DATE_RFC2822)) . '\n/', $result); $this->assertPattern('/X-Mailer: CakePHP Email Component\n/', $result); $this->assertPattern('/Content-Type: text\/plain; charset=UTF-8\n/', $result); - $this->assertPattern('/Content-Transfer-Encoding: 7bitParameters:\n/', $result); + $this->assertPattern('/Content-Transfer-Encoding: 7bitMessage:\n/', $result); $this->assertPattern('/This is the body of the message/', $result); $this->Controller->Session = $session; } @@ -808,14 +435,14 @@ HTMLBLOC; 'View' => array(LIBS . 'tests' . DS . 'test_app' . DS . 'View'. DS) )); - $this->Controller->EmailTest->to = 'postmaster@localhost'; + $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Cake Debug Test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->layout = 'default'; $this->Controller->EmailTest->template = null; - $this->Controller->EmailTest->delivery = 'debug'; + $this->Controller->EmailTest->delivery = 'DebugComp'; $text = $html = 'This is the body of the message'; @@ -849,14 +476,14 @@ HTMLBLOC; $this->Controller->set('value', 22091985); $this->Controller->set('title_for_layout', 'EmailTest'); - $this->Controller->EmailTest->to = 'postmaster@localhost'; + $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Cake Debug Test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->layout = 'default'; $this->Controller->EmailTest->template = 'custom'; - $this->Controller->EmailTest->delivery = 'debug'; + $this->Controller->EmailTest->delivery = 'DebugComp'; $text = <<Controller->EmailTest->to = 'postmaster@localhost'; + $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Cake Debug Test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->template = null; - $this->Controller->EmailTest->delivery = 'debug'; + $this->Controller->EmailTest->delivery = 'DebugComp'; $content = array('First line', 'Second line', 'Third line'); $this->assertTrue($this->Controller->EmailTest->send($content)); - $result = $this->Controller->Session->read('Message.email.message'); + $result = DebugCompTransport::$lastEmail; - $this->assertPattern('/To: postmaster@localhost\n/', $result); + $this->assertPattern('/To: postmaster@example.com\n/', $result); $this->assertPattern('/Subject: Cake Debug Test\n/', $result); $this->assertPattern('/Reply-To: noreply@example.com\n/', $result); $this->assertPattern('/From: noreply@example.com\n/', $result); $this->assertPattern('/X-Mailer: CakePHP Email Component\n/', $result); $this->assertPattern('/Content-Type: text\/plain; charset=UTF-8\n/', $result); - $this->assertPattern('/Content-Transfer-Encoding: 7bitParameters:\n/', $result); + $this->assertPattern('/Content-Transfer-Encoding: 7bitMessage:\n/', $result); $this->assertPattern('/First line\n/', $result); $this->assertPattern('/Second line\n/', $result); $this->assertPattern('/Third line\n/', $result); @@ -931,15 +558,15 @@ HTMLBLOC; * @return void */ function testDateProperty() { - $this->Controller->EmailTest->to = 'postmaster@localhost'; + $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Cake Debug Test'; $this->Controller->EmailTest->date = 'Today!'; $this->Controller->EmailTest->template = null; - $this->Controller->EmailTest->delivery = 'debug'; + $this->Controller->EmailTest->delivery = 'DebugComp'; $this->assertTrue($this->Controller->EmailTest->send('test message')); - $result = $this->Controller->Session->read('Message.email.message'); + $result = DebugCompTransport::$lastEmail; $this->assertPattern('/Date: Today!\n/', $result); } @@ -983,19 +610,19 @@ HTMLBLOC; mb_internal_encoding('ISO-8859-1'); $this->Controller->charset = 'UTF-8'; - $this->Controller->EmailTest->to = 'postmaster@localhost'; + $this->Controller->EmailTest->to = 'postmaster@example.com'; $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->delivery = 'DebugComp'; $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); + preg_match('/Subject: (.*)Header:/s', DebugCompTransport::$lastEmail, $matches); $this->assertEqual(trim($matches[1]), $subject); $result = mb_internal_encoding(); @@ -1012,28 +639,28 @@ HTMLBLOC; */ function testMultibyte() { $this->Controller->charset = 'UTF-8'; - $this->Controller->EmailTest->to = 'postmaster@localhost'; + $this->Controller->EmailTest->to = 'postmaster@example.com'; $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->delivery = 'DebugComp'; $subject = '=?UTF-8?B?2YfYsNmHINix2LPYp9mE2Kkg2KjYudmG2YjYp9mGINi32YjZitmEINmF2LE=?=' . "\r\n" . ' =?UTF-8?B?2LPZhCDZhNmE2YXYs9iq2YTZhQ==?='; $this->Controller->EmailTest->sendAs = 'text'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); - preg_match('/Subject: (.*)Header:/s', $this->Controller->Session->read('Message.email.message'), $matches); + preg_match('/Subject: (.*)Header:/s', DebugCompTransport::$lastEmail, $matches); $this->assertEqual(trim($matches[1]), $subject); $this->Controller->EmailTest->sendAs = 'html'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); - preg_match('/Subject: (.*)Header:/s', $this->Controller->Session->read('Message.email.message'), $matches); + preg_match('/Subject: (.*)Header:/s', DebugCompTransport::$lastEmail, $matches); $this->assertEqual(trim($matches[1]), $subject); $this->Controller->EmailTest->sendAs = 'both'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); - preg_match('/Subject: (.*)Header:/s', $this->Controller->Session->read('Message.email.message'), $matches); + preg_match('/Subject: (.*)Header:/s', DebugCompTransport::$lastEmail, $matches); $this->assertEqual(trim($matches[1]), $subject); } @@ -1043,12 +670,12 @@ HTMLBLOC; * @return void */ public function testSendWithAttachments() { - $this->Controller->EmailTest->to = 'postmaster@localhost'; + $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Attachment Test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->template = null; - $this->Controller->EmailTest->delivery = 'debug'; + $this->Controller->EmailTest->delivery = 'DebugComp'; $this->Controller->EmailTest->attachments = array( __FILE__, 'some-name.php' => __FILE__ @@ -1057,7 +684,7 @@ HTMLBLOC; $this->Controller->EmailTest->sendAs = 'text'; $this->assertTrue($this->Controller->EmailTest->send($body)); - $msg = $this->Controller->Session->read('Message.email.message'); + $msg = DebugCompTransport::$lastEmail; $this->assertPattern('/' . preg_quote('Content-Disposition: attachment; filename="EmailComponentTest.php"') . '/', $msg); $this->assertPattern('/' . preg_quote('Content-Disposition: attachment; filename="some-name.php"') . '/', $msg); } @@ -1068,30 +695,30 @@ HTMLBLOC; * @return void */ public function testSendAsIsNotIgnoredIfAttachmentsPresent() { - $this->Controller->EmailTest->to = 'postmaster@localhost'; + $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Attachment Test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->template = null; - $this->Controller->EmailTest->delivery = 'debug'; + $this->Controller->EmailTest->delivery = 'DebugComp'; $this->Controller->EmailTest->attachments = array(__FILE__); $body = '

This is the body of the message

'; $this->Controller->EmailTest->sendAs = 'html'; $this->assertTrue($this->Controller->EmailTest->send($body)); - $msg = $this->Controller->Session->read('Message.email.message'); + $msg = DebugCompTransport::$lastEmail; $this->assertNoPattern('/text\/plain/', $msg); $this->assertPattern('/text\/html/', $msg); $this->Controller->EmailTest->sendAs = 'text'; $this->assertTrue($this->Controller->EmailTest->send($body)); - $msg = $this->Controller->Session->read('Message.email.message'); + $msg = DebugCompTransport::$lastEmail; $this->assertPattern('/text\/plain/', $msg); $this->assertNoPattern('/text\/html/', $msg); $this->Controller->EmailTest->sendAs = 'both'; $this->assertTrue($this->Controller->EmailTest->send($body)); - $msg = $this->Controller->Session->read('Message.email.message'); + $msg = DebugCompTransport::$lastEmail; $this->assertNoPattern('/text\/plain/', $msg); $this->assertNoPattern('/text\/html/', $msg); @@ -1104,17 +731,17 @@ HTMLBLOC; * @return void */ public function testNoDoubleNewlinesInHeaders() { - $this->Controller->EmailTest->to = 'postmaster@localhost'; + $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Attachment Test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->template = null; - $this->Controller->EmailTest->delivery = 'debug'; + $this->Controller->EmailTest->delivery = 'DebugComp'; $body = '

This is the body of the message

'; $this->Controller->EmailTest->sendAs = 'both'; $this->assertTrue($this->Controller->EmailTest->send($body)); - $msg = $this->Controller->Session->read('Message.email.message'); + $msg = DebugCompTransport::$lastEmail; $this->assertNoPattern('/\n\nContent-Transfer-Encoding/', $msg); $this->assertPattern('/\nContent-Transfer-Encoding/', $msg); @@ -1127,7 +754,7 @@ HTMLBLOC; * @return void */ function testReset() { - $this->Controller->EmailTest->template = 'test_template'; + $this->Controller->EmailTest->template = 'default'; $this->Controller->EmailTest->to = 'test.recipient@example.com'; $this->Controller->EmailTest->from = 'test.sender@example.com'; $this->Controller->EmailTest->replyTo = 'test.replyto@example.com'; @@ -1164,9 +791,6 @@ HTMLBLOC; $this->assertNull($this->Controller->EmailTest->date); $this->assertNull($this->Controller->EmailTest->subject); $this->assertNull($this->Controller->EmailTest->additionalParams); - $this->assertIdentical($this->Controller->EmailTest->getHeaders(), array()); - $this->assertNull($this->Controller->EmailTest->getBoundary()); - $this->assertIdentical($this->Controller->EmailTest->getMessage(), array()); $this->assertNull($this->Controller->EmailTest->smtpError); $this->assertIdentical($this->Controller->EmailTest->attachments, array()); $this->assertNull($this->Controller->EmailTest->textMessage); @@ -1181,14 +805,14 @@ HTMLBLOC; $this->Controller->view = 'TestPlugin.Email'; - $this->Controller->EmailTest->to = 'postmaster@localhost'; + $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'CustomViewClass test'; - $this->Controller->EmailTest->delivery = 'debug'; + $this->Controller->EmailTest->delivery = 'DebugComp'; $body = 'Body of message'; $this->assertTrue($this->Controller->EmailTest->send($body)); - $result = $this->Controller->Session->read('Message.email.message'); + $result = DebugCompTransport::$lastEmail; $this->assertPattern('/Body of message/', $result); @@ -1211,110 +835,31 @@ HTMLBLOC; * @return void */ function testMessageId() { - $this->Controller->EmailTest->to = 'postmaster@localhost'; + $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Cake Debug Test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->template = null; - $this->Controller->EmailTest->delivery = 'debug'; + $this->Controller->EmailTest->delivery = 'DebugComp'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); - $result = $this->Controller->Session->read('Message.email.message'); + $result = DebugCompTransport::$lastEmail; $this->assertPattern('/Message-ID: \<[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}@' . env('HTTP_HOST') . '\>\n/', $result); - $this->Controller->EmailTest->messageId = '<22091985.998877@localhost>'; + $this->Controller->EmailTest->messageId = '<22091985.998877@example.com>'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); - $result = $this->Controller->Session->read('Message.email.message'); + $result = DebugCompTransport::$lastEmail; - $this->assertPattern('/Message-ID: <22091985.998877@localhost>\n/', $result); + $this->assertPattern('/Message-ID: <22091985.998877@example.com>\n/', $result); $this->Controller->EmailTest->messageId = false; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); - $result = $this->Controller->Session->read('Message.email.message'); + $result = DebugCompTransport::$lastEmail; $this->assertNoPattern('/Message-ID:/', $result); } -/** - * testSendMessage method - * - * @access public - * @return void - */ - function testSendMessage() { - $this->Controller->EmailTest->delivery = 'getMessage'; - $this->Controller->EmailTest->lineLength = 70; - - $text = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'; - $this->Controller->EmailTest->sendAs = 'text'; - $result = $this->Controller->EmailTest->send($text); - $expected = array( - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do', - 'eiusmod tempor incididunt ut labore et dolore magna aliqua.', - '', - '' - ); - $this->assertEqual($expected, $result); - - $text = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.'; - $this->Controller->EmailTest->sendAs = 'html'; - $result = $this->Controller->EmailTest->send($text); - $expected = array( - $text, - '', - '' - ); - $this->assertEqual($expected, $result); - } - -/** - * Test that _formatName doesn't jack up email addresses with alias parts. - * - * @return void - */ - function testFormatAddressAliases() { - $result = $this->Controller->EmailTest->formatAddress('email@example.com'); - $this->assertEqual($result, 'email@example.com'); - - $result = $this->Controller->EmailTest->formatAddress('alias '); - $this->assertEqual($result, 'alias '); - - $result = $this->Controller->EmailTest->formatAddress('alias'); - $this->assertEqual($result, 'alias '); - - $result = $this->Controller->EmailTest->formatAddress('email@example.com'); - $this->assertEqual($result, 'email@example.com'); - - $result = $this->Controller->EmailTest->formatAddress(''); - $this->assertEqual($result, ''); - - $result = $this->Controller->EmailTest->formatAddress('email@example.com', true); - $this->assertEqual($result, ''); - - $result = $this->Controller->EmailTest->formatAddress('', true); - $this->assertEqual($result, ''); - - $result = $this->Controller->EmailTest->formatAddress('alias name ', true); - $this->assertEqual($result, ''); - } - -/** - * test formatting addresses with multibyte chars - * - * @return void - */ - function testFormatAddressMultibyte() { - $this->Controller->EmailTest->charset = 'UTF-8'; - $result = $this->Controller->EmailTest->formatAddress('ÄÖÜTest '); - $this->assertEqual($result, '=?UTF-8?B?w4TDlsOcVGVzdCA=?= '); - - $result = $this->Controller->EmailTest->formatAddress('ÄÖÜTest'); - $this->assertEqual($result, '=?UTF-8?B?w4TDlsOcVGVzdA==?= '); - - $result = $this->Controller->EmailTest->formatAddress('ÄÖÜTest ', true); - $this->assertEqual($result, ''); - } } diff --git a/lib/Cake/tests/Case/Controller/ControllerTest.php b/lib/Cake/tests/Case/Controller/ControllerTest.php index 82ea88dbe..2a25a281b 100644 --- a/lib/Cake/tests/Case/Controller/ControllerTest.php +++ b/lib/Cake/tests/Case/Controller/ControllerTest.php @@ -1040,7 +1040,7 @@ class ControllerTest extends CakeTestCase { $comment = new ControllerComment($request); $comment->set('someVar', 'data'); $result = $TestController->validateErrors($comment); - $expected = array('some_field' => 'error_message', 'some_field2' => 'error_message2'); + $expected = array('some_field' => array('error_message'), 'some_field2' => array('error_message2')); $this->assertIdentical($result, $expected); $this->assertEqual($TestController->validate($comment), 2); } @@ -1058,7 +1058,7 @@ class ControllerTest extends CakeTestCase { $Post->set('title', ''); $result = $TestController->validateErrors($Post); - $expected = array('title' => 'This field cannot be left blank'); + $expected = array('title' => array('This field cannot be left blank')); $this->assertEqual($result, $expected); } diff --git a/lib/Cake/tests/Case/Core/ObjectTest.php b/lib/Cake/tests/Case/Core/ObjectTest.php index 0c959065e..a9729255d 100644 --- a/lib/Cake/tests/Case/Core/ObjectTest.php +++ b/lib/Cake/tests/Case/Core/ObjectTest.php @@ -683,9 +683,9 @@ class ObjectTest extends CakeTestCase { */ function testRequestAction() { App::build(array( - 'models' => array(LIBS . 'tests' . DS . 'test_app' . DS . 'models' . DS), - 'views' => array(LIBS . 'tests' . DS . 'test_app' . DS . 'views' . DS), - 'controllers' => array(LIBS . 'tests' . DS . 'test_app' . DS . 'controllers' . DS) + 'models' => array(LIBS . 'tests' . DS . 'test_app' . DS . 'Model' . DS), + 'views' => array(LIBS . 'tests' . DS . 'test_app' . DS . 'View' . DS), + 'controllers' => array(LIBS . 'tests' . DS . 'test_app' . DS . 'Controller' . DS) )); $result = $this->object->requestAction(''); $this->assertFalse($result); @@ -763,9 +763,9 @@ class ObjectTest extends CakeTestCase { */ function testRequestActionArray() { App::build(array( - 'models' => array(LIBS . 'tests' . DS . 'test_app' . DS . 'models' . DS), - 'views' => array(LIBS . 'tests' . DS . 'test_app' . DS . 'views' . DS), - 'controllers' => array(LIBS . 'tests' . DS . 'test_app' . DS . 'controllers' . DS) + 'models' => array(LIBS . 'tests' . DS . 'test_app' . DS . 'Model' . DS), + 'views' => array(LIBS . 'tests' . DS . 'test_app' . DS . 'View' . DS), + 'controllers' => array(LIBS . 'tests' . DS . 'test_app' . DS . 'Controller' . DS) )); $result = $this->object->requestAction( @@ -819,8 +819,7 @@ class ObjectTest extends CakeTestCase { */ function testRequestActionParamParseAndPass() { $result = $this->object->requestAction('/request_action/params_pass'); - $this->assertTrue(isset($result['url']['url'])); - $this->assertEqual($result['url']['url'], 'request_action/params_pass'); + $this->assertEqual($result->url, 'request_action/params_pass'); $this->assertEqual($result['controller'], 'request_action'); $this->assertEqual($result['action'], 'params_pass'); $this->assertEqual($result['form'], array()); diff --git a/lib/Cake/tests/Case/Error/ErrorHandlerTest.php b/lib/Cake/tests/Case/Error/ErrorHandlerTest.php index fd76ac7d1..7fc875aea 100644 --- a/lib/Cake/tests/Case/Error/ErrorHandlerTest.php +++ b/lib/Cake/tests/Case/Error/ErrorHandlerTest.php @@ -36,7 +36,7 @@ class ErrorHandlerTest extends CakeTestCase { */ function setUp() { App::build(array( - 'views' => array( + 'View' => array( LIBS . 'tests' . DS . 'test_app' . DS . 'views'. DS, LIBS . 'libs' . DS . 'view' . DS ) diff --git a/lib/Cake/tests/Case/I18n/MultibyteTest.php b/lib/Cake/tests/Case/I18n/MultibyteTest.php index 692dd85bd..fab3bb327 100644 --- a/lib/Cake/tests/Case/I18n/MultibyteTest.php +++ b/lib/Cake/tests/Case/I18n/MultibyteTest.php @@ -6592,7 +6592,7 @@ class MultibyteTest extends CakeTestCase { $string = 'ԀԂԄԆԈԊԌԎԐԒ'; $result = mb_strtolower($string); - $expected = 'ԁԃԅԇԉԋԍԏԐԒ'; + $expected = 'ԁԃԅԇԉԋԍԏԑԓ'; $this->assertEqual($result, $expected); $string = 'ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉՊՋՌՍՎՏՐՑՒՓՔՕՖև'; diff --git a/lib/Cake/tests/Case/Model/Behavior/TranslateBehaviorTest.php b/lib/Cake/tests/Case/Model/Behavior/TranslateBehaviorTest.php index 292f0cdf0..cae244644 100644 --- a/lib/Cake/tests/Case/Model/Behavior/TranslateBehaviorTest.php +++ b/lib/Cake/tests/Case/Model/Behavior/TranslateBehaviorTest.php @@ -670,7 +670,7 @@ class TranslateBehaviorTest extends CakeTestCase { )); $TestModel->create(); $this->assertFalse($TestModel->save($data)); - $this->assertEqual($TestModel->validationErrors['title'], 'This field cannot be left blank'); + $this->assertEqual($TestModel->validationErrors['title'], array('This field cannot be left blank')); $TestModel->locale = 'eng'; $TestModel->validate['title'] = '/Only this title/'; diff --git a/lib/Cake/tests/Case/Model/BehaviorCollectionTest.php b/lib/Cake/tests/Case/Model/BehaviorCollectionTest.php index 6724c2784..907b127c5 100644 --- a/lib/Cake/tests/Case/Model/BehaviorCollectionTest.php +++ b/lib/Cake/tests/Case/Model/BehaviorCollectionTest.php @@ -990,11 +990,11 @@ class BehaviorCollectionTest extends CakeTestCase { $Apple->Behaviors->attach('Test', array('validate' => 'on')); $this->assertIdentical($Apple->validates(), false); - $this->assertIdentical($Apple->validationErrors, array('name' => true)); + $this->assertIdentical($Apple->validationErrors, array('name' => array(true))); $Apple->Behaviors->attach('Test', array('validate' => 'stop')); $this->assertIdentical($Apple->validates(), false); - $this->assertIdentical($Apple->validationErrors, array('name' => true)); + $this->assertIdentical($Apple->validationErrors, array('name' => array(true, true))); $Apple->Behaviors->attach('Test', array('validate' => 'whitelist')); $Apple->validates(); diff --git a/lib/Cake/tests/Case/Model/ModelValidationTest.php b/lib/Cake/tests/Case/Model/ModelValidationTest.php index 8bec80494..8cc48aa3f 100644 --- a/lib/Cake/tests/Case/Model/ModelValidationTest.php +++ b/lib/Cake/tests/Case/Model/ModelValidationTest.php @@ -49,7 +49,7 @@ class ModelValidationTest extends BaseModelTest { 'validator' => array( 'rule' => 'customValidatorWithParams', 'on' => null, - 'last' => false, + 'last' => true, 'allowEmpty' => false, 'required' => true ), @@ -63,7 +63,7 @@ class ModelValidationTest extends BaseModelTest { 'required' => true ); $expected = array( - 'title' => 'This field will *never* validate! Muhahaha!' + 'title' => array('This field will *never* validate! Muhahaha!') ); $this->assertEqual($TestModel->invalidFields(), $expected); @@ -85,7 +85,7 @@ class ModelValidationTest extends BaseModelTest { 'five' => array( 'rule' => array(1 => 'one', 2 => 'two', 3 => null, 4 => 'four'), 'on' => null, - 'last' => false, + 'last' => true, 'allowEmpty' => false, 'required' => true ), @@ -111,7 +111,7 @@ class ModelValidationTest extends BaseModelTest { 'six' => array( 'rule' => array(1 => 'one', 2 => array('two'), 3 => null, 4 => 'four', 5 => array('five' => 5)), 'on' => null, - 'last' => false, + 'last' => true, 'allowEmpty' => false, 'required' => true ) @@ -139,29 +139,29 @@ class ModelValidationTest extends BaseModelTest { $TestModel->set(array('title' => '$$', 'name' => '##')); $TestModel->invalidFields(array('fieldList' => array('title'))); $expected = array( - 'title' => 'This field cannot be left blank' + 'title' => array('This field cannot be left blank') ); $this->assertEqual($TestModel->validationErrors, $expected); $TestModel->validationErrors = array(); $TestModel->invalidFields(array('fieldList' => array('name'))); $expected = array( - 'name' => 'This field cannot be left blank' + 'name' => array('This field cannot be left blank') ); $this->assertEqual($TestModel->validationErrors, $expected); $TestModel->validationErrors = array(); $TestModel->invalidFields(array('fieldList' => array('name', 'title'))); $expected = array( - 'name' => 'This field cannot be left blank', - 'title' => 'This field cannot be left blank' + 'name' => array('This field cannot be left blank'), + 'title' => array('This field cannot be left blank') ); $this->assertEqual($TestModel->validationErrors, $expected); $TestModel->validationErrors = array(); $TestModel->whitelist = array('name'); $TestModel->invalidFields(); - $expected = array('name' => 'This field cannot be left blank'); + $expected = array('name' => array('This field cannot be left blank')); $this->assertEqual($TestModel->validationErrors, $expected); $this->assertEqual($TestModel->validate, $validate); @@ -187,7 +187,7 @@ class ModelValidationTest extends BaseModelTest { $TestModel->whitelist = array('name'); $TestModel->save(array('name' => '#$$#', 'title' => '$$$$')); - $expected = array('name' => 'This field cannot be left blank'); + $expected = array('name' => array('This field cannot be left blank')); $this->assertEqual($TestModel->validationErrors, $expected); } @@ -518,7 +518,7 @@ class ModelValidationTest extends BaseModelTest { $this->assertFalse($result); $result = $TestModel->validationErrors; $expected = array( - 'title' => 'onlyLetters' + 'title' => array('tooShort') ); $this->assertEqual($result, $expected); @@ -526,7 +526,7 @@ class ModelValidationTest extends BaseModelTest { 'title' => array( 'tooShort' => array( 'rule' => array('minLength', 50), - 'last' => true + 'last' => false ), 'onlyLetters' => array('rule' => '/^[a-z]+$/i') ), @@ -539,7 +539,7 @@ class ModelValidationTest extends BaseModelTest { $this->assertFalse($result); $result = $TestModel->validationErrors; $expected = array( - 'title' => 'tooShort' + 'title' => array('tooShort', 'onlyLetters') ); $this->assertEqual($result, $expected); } @@ -569,7 +569,7 @@ class ModelValidationTest extends BaseModelTest { $JoinThing->validate = array('doomed' => array('rule' => 'notEmpty')); - $expectedError = array('doomed' => 'This field cannot be left blank'); + $expectedError = array('doomed' => array('This field cannot be left blank')); $Something->create(); $result = $Something->save($data); @@ -621,7 +621,7 @@ class ModelValidationTest extends BaseModelTest { $JoinThing =& $Something->JoinThing; $JoinThing->validate = array('doomed' => array('rule' => 'notEmpty')); - $expectedError = array('doomed' => 'This field cannot be left blank'); + $expectedError = array('doomed' => array('This field cannot be left blank')); $Something->create(); $result = $Something->saveAll($data, array('validate' => 'only')); diff --git a/lib/Cake/tests/Case/Model/ModelWriteTest.php b/lib/Cake/tests/Case/Model/ModelWriteTest.php index 026ca90d3..466c703d8 100644 --- a/lib/Cake/tests/Case/Model/ModelWriteTest.php +++ b/lib/Cake/tests/Case/Model/ModelWriteTest.php @@ -2765,8 +2765,8 @@ class ModelWriteTest extends BaseModelTest { array('validate' => 'first') ), false); $expected = array( - 'Comment' => array('comment' => 'This field cannot be left blank'), - 'Attachment' => array('attachment' => 'This field cannot be left blank') + 'Comment' => array('comment' => array('This field cannot be left blank')), + 'Attachment' => array('attachment' => array('This field cannot be left blank')) ); $this->assertEqual($model->validationErrors, $expected['Comment']); $this->assertEqual($model->Attachment->validationErrors, $expected['Attachment']); @@ -2956,11 +2956,11 @@ class ModelWriteTest extends BaseModelTest { $this->assertEqual($result, $expected); $expected = array('Comment' => array( - array('comment' => 'This field cannot be left blank') + array('comment' => array('This field cannot be left blank')) )); $this->assertEqual($TestModel->validationErrors, $expected); $expected = array( - array('comment' => 'This field cannot be left blank') + array('comment' => array('This field cannot be left blank')) ); $this->assertEqual($TestModel->Comment->validationErrors, $expected); @@ -3356,7 +3356,7 @@ class ModelWriteTest extends BaseModelTest { $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')); + $errors = array(1 => array('title' => array('This field cannot be left blank'))); $transactionWorked = Set::matches('/Post[1][title=Baleeted First Post]', $result); if (!$transactionWorked) { $this->assertTrue(Set::matches('/Post[1][title=Un-Baleeted First Post]', $result)); @@ -3381,7 +3381,7 @@ class ModelWriteTest extends BaseModelTest { $result = $TestModel->saveAll($data, array('validate' => true, 'atomic' => false)); $this->assertEqual($result, array(true, false)); $result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC')); - $errors = array(1 => array('title' => 'This field cannot be left blank')); + $errors = array(1 => array('title' => array('This field cannot be left blank'))); $newTs = date('Y-m-d H:i:s'); $expected = array( array( @@ -3494,7 +3494,7 @@ class ModelWriteTest extends BaseModelTest { ); $this->assertFalse($result); $expected = array( - 0 => array('title' => 'This field cannot be left blank'), + 0 => array('title' => array('This field cannot be left blank')), ); $this->assertEqual($TestModel->validationErrors, $expected); @@ -3508,7 +3508,7 @@ class ModelWriteTest extends BaseModelTest { ); $this->assertFalse($result); $expected = array( - 1 => array('title' => 'This field cannot be left blank'), + 1 => array('title' => array('This field cannot be left blank')), ); $this->assertEqual($TestModel->validationErrors, $expected); } @@ -3541,7 +3541,7 @@ class ModelWriteTest extends BaseModelTest { $result = $model->find('all'); $this->assertEqual($result, array()); $expected = array('Comment' => array( - 1 => array('comment' => 'This field cannot be left blank') + 1 => array('comment' => array('This field cannot be left blank')) )); $this->assertEqual($model->Comment->validationErrors, $expected['Comment']); @@ -3747,14 +3747,14 @@ class ModelWriteTest extends BaseModelTest { $this->assertIdentical($result, $expected); $expected = array('Comment' => array( - 0 => array('comment' => 'This field cannot be left blank'), - 2 => array('comment' => 'This field cannot be left blank') + 0 => array('comment' => array('This field cannot be left blank')), + 2 => array('comment' => array('This field cannot be left blank')) )); $this->assertEqual($TestModel->validationErrors, $expected); $expected = array( - 0 => array('comment' => 'This field cannot be left blank'), - 2 => array('comment' => 'This field cannot be left blank') + 0 => array('comment' => array('This field cannot be left blank')), + 2 => array('comment' => array('This field cannot be left blank')) ); $this->assertEqual($TestModel->Comment->validationErrors, $expected); } diff --git a/lib/Cake/tests/Case/Network/CakeEmailTest.php b/lib/Cake/tests/Case/Network/CakeEmailTest.php new file mode 100644 index 000000000..d44a602b9 --- /dev/null +++ b/lib/Cake/tests/Case/Network/CakeEmailTest.php @@ -0,0 +1,827 @@ + + * Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice + * + * @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests + * @package cake.tests.cases.libs + * @since CakePHP(tm) v 2.0.0 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +App::uses('CakeEmail', 'Network'); + +/** + * Help to test CakeEmail + * + */ +class TestCakeEmail extends CakeEmail { + +/** + * Config + * + */ + protected $_config = array(); + +/** + * Wrap to protected method + * + */ + public function formatAddress($address) { + return parent::_formatAddress($address); + } + +/** + * Wrap to protected method + * + */ + public function wrap($text) { + return parent::_wrap($text); + } + +/** + * Get the boundary attribute + * + * @return string + */ + public function getBoundary() { + return $this->_boundary; + } + +} + +/** + * Debug transport email + * + */ +class DebugTransport extends AbstractTransport { + +/** + * Last email body + * + * @var string + */ + public static $lastEmail = ''; + +/** + * Last email header + * + * @var string + */ + public static $lastHeader = ''; + +/** + * Include addresses in header + * + * @var boolean + */ + public static $includeAddresses = false; + +/** + * Config + * + * @var array + */ + public static $config = array(); + +/** + * Config + * + * @param mixed $config + * @return mixed + */ + public function config($config) { + self::$config = $config; + } + +/** + * Send + * + * @param object $email CakeEmail + * @return boolean + */ + public function send(CakeEmail $email) { + self::$lastEmail = implode("\r\n", $email->message()); + $options = array(); + if (self::$includeAddresses) { + $options = array_fill_keys(array('from', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'bcc'), true); + } + self::$lastHeader = $this->_headersToString($email->getHeaders($options)); + return true; + } + +} + +/** + * CakeEmailTest class + * + * @package cake.tests.cases.libs + */ +class CakeEmailTest extends CakeTestCase { + +/** + * setUp + * + * @return void + */ + public function setUp() { + parent::setUp(); + $this->CakeEmail = new TestCakeEmail(); + + App::build(array( + 'views' => array(CAKE . 'tests' . DS . 'test_app' . DS . 'View'. DS) + )); + } + +/** + * tearDown method + * + * @return void + */ + function tearDown() { + parent::tearDown(); + App::build(); + } + +/** + * testFrom method + * + * @return void + */ + public function testFrom() { + $this->assertIdentical($this->CakeEmail->from(), array()); + + $this->CakeEmail->from('cake@cakephp.org'); + $expected = array('cake@cakephp.org' => 'cake@cakephp.org'); + $this->assertIdentical($this->CakeEmail->from(), $expected); + + $this->CakeEmail->from(array('cake@cakephp.org')); + $this->assertIdentical($this->CakeEmail->from(), $expected); + + $this->CakeEmail->from('cake@cakephp.org', 'CakePHP'); + $expected = array('cake@cakephp.org' => 'CakePHP'); + $this->assertIdentical($this->CakeEmail->from(), $expected); + + $result = $this->CakeEmail->from(array('cake@cakephp.org' => 'CakePHP')); + $this->assertIdentical($this->CakeEmail->from(), $expected); + $this->assertIdentical($this->CakeEmail, $result); + } + +/** + * testSender method + * + * @return void + */ + public function testSender() { + $this->CakeEmail->reset(); + $this->assertIdentical($this->CakeEmail->sender(), array()); + + $this->CakeEmail->sender('cake@cakephp.org', 'Name'); + $expected = array('cake@cakephp.org' => 'Name'); + $this->assertIdentical($this->CakeEmail->sender(), $expected); + + $headers = $this->CakeEmail->getHeaders(array('from' => true, 'sender' => true)); + $this->assertIdentical($headers['From'], false); + $this->assertIdentical($headers['Sender'], 'Name '); + + $this->CakeEmail->from('cake@cakephp.org', 'CakePHP'); + $headers = $this->CakeEmail->getHeaders(array('from' => true, 'sender' => true)); + $this->assertIdentical($headers['From'], 'CakePHP '); + $this->assertIdentical($headers['Sender'], ''); + } + +/** + * testTo method + * + * @return void + */ + public function testTo() { + $this->assertIdentical($this->CakeEmail->to(), array()); + + $result = $this->CakeEmail->to('cake@cakephp.org'); + $expected = array('cake@cakephp.org' => 'cake@cakephp.org'); + $this->assertIdentical($this->CakeEmail->to(), $expected); + $this->assertIdentical($this->CakeEmail, $result); + + $this->CakeEmail->to('cake@cakephp.org', 'CakePHP'); + $expected = array('cake@cakephp.org' => 'CakePHP'); + $this->assertIdentical($this->CakeEmail->to(), $expected); + + $list = array( + 'cake@cakephp.org' => 'Cake PHP', + 'cake-php@googlegroups.com' => 'Cake Groups', + 'root@cakephp.org' + ); + $this->CakeEmail->to($list); + $expected = array( + 'cake@cakephp.org' => 'Cake PHP', + 'cake-php@googlegroups.com' => 'Cake Groups', + 'root@cakephp.org' => 'root@cakephp.org' + ); + $this->assertIdentical($this->CakeEmail->to(), $expected); + + $this->CakeEmail->addTo('jrbasso@cakephp.org'); + $this->CakeEmail->addTo('mark_story@cakephp.org', 'Mark Story'); + $result = $this->CakeEmail->addTo(array('phpnut@cakephp.org' => 'PhpNut', 'jose_zap@cakephp.org')); + $expected = array( + 'cake@cakephp.org' => 'Cake PHP', + 'cake-php@googlegroups.com' => 'Cake Groups', + 'root@cakephp.org' => 'root@cakephp.org', + 'jrbasso@cakephp.org' => 'jrbasso@cakephp.org', + 'mark_story@cakephp.org' => 'Mark Story', + 'phpnut@cakephp.org' => 'PhpNut', + 'jose_zap@cakephp.org' => 'jose_zap@cakephp.org' + ); + $this->assertIdentical($this->CakeEmail->to(), $expected); + $this->assertIdentical($this->CakeEmail, $result); + } + +/** + * Data provider function for testBuildInvalidData + * + * @return array + */ + public static function invalidEmails() { + return array( + array(1.0), + array(''), + array('string'), + array(''), + array('some@one.whereis'), + array(array('ok@cakephp.org', 1.0, '', 'string')) + ); + } + +/** + * testBuildInvalidData + * + * @dataProvider invalidEmails + * @expectedException SocketException + * @return void + */ + public function testInvalidEmail($value) { + $this->CakeEmail->to($value); + } + +/** + * testFormatAddress method + * + * @return void + */ + public function testFormatAddress() { + $result = $this->CakeEmail->formatAddress(array('cake@cakephp.org' => 'cake@cakephp.org')); + $expected = array('cake@cakephp.org'); + $this->assertIdentical($result, $expected); + + $result = $this->CakeEmail->formatAddress(array('cake@cakephp.org' => 'cake@cakephp.org', 'php@cakephp.org' => 'php@cakephp.org')); + $expected = array('cake@cakephp.org', 'php@cakephp.org'); + $this->assertIdentical($result, $expected); + + $result = $this->CakeEmail->formatAddress(array('cake@cakephp.org' => 'CakePHP', 'php@cakephp.org' => 'Cake')); + $expected = array('CakePHP ', 'Cake '); + $this->assertIdentical($result, $expected); + + $result = $this->CakeEmail->formatAddress(array('cake@cakephp.org' => 'ÄÖÜTest')); + $expected = array('=?UTF-8?B?w4TDlsOcVGVzdA==?= '); + $this->assertIdentical($result, $expected); + } + +/** + * testAddresses method + * + * @return void + */ + public function testAddresses() { + $this->CakeEmail->reset(); + $this->CakeEmail->from('cake@cakephp.org', 'CakePHP'); + $this->CakeEmail->replyTo('replyto@cakephp.org', 'ReplyTo CakePHP'); + $this->CakeEmail->readReceipt('readreceipt@cakephp.org', 'ReadReceipt CakePHP'); + $this->CakeEmail->returnPath('returnpath@cakephp.org', 'ReturnPath CakePHP'); + $this->CakeEmail->to('to@cakephp.org', 'To CakePHP'); + $this->CakeEmail->cc('cc@cakephp.org', 'Cc CakePHP'); + $this->CakeEmail->bcc('bcc@cakephp.org', 'Bcc CakePHP'); + $this->CakeEmail->addTo('to2@cakephp.org', 'To2 CakePHP'); + $this->CakeEmail->addCc('cc2@cakephp.org', 'Cc2 CakePHP'); + $this->CakeEmail->addBcc('bcc2@cakephp.org', 'Bcc2 CakePHP'); + + $this->assertIdentical($this->CakeEmail->from(), array('cake@cakephp.org' => 'CakePHP')); + $this->assertIdentical($this->CakeEmail->replyTo(), array('replyto@cakephp.org' => 'ReplyTo CakePHP')); + $this->assertIdentical($this->CakeEmail->readReceipt(), array('readreceipt@cakephp.org' => 'ReadReceipt CakePHP')); + $this->assertIdentical($this->CakeEmail->returnPath(), array('returnpath@cakephp.org' => 'ReturnPath CakePHP')); + $this->assertIdentical($this->CakeEmail->to(), array('to@cakephp.org' => 'To CakePHP', 'to2@cakephp.org' => 'To2 CakePHP')); + $this->assertIdentical($this->CakeEmail->cc(), array('cc@cakephp.org' => 'Cc CakePHP', 'cc2@cakephp.org' => 'Cc2 CakePHP')); + $this->assertIdentical($this->CakeEmail->bcc(), array('bcc@cakephp.org' => 'Bcc CakePHP', 'bcc2@cakephp.org' => 'Bcc2 CakePHP')); + + $headers = $this->CakeEmail->getHeaders(array_fill_keys(array('from', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'bcc'), true)); + $this->assertIdentical($headers['From'], 'CakePHP '); + $this->assertIdentical($headers['Reply-To'], 'ReplyTo CakePHP '); + $this->assertIdentical($headers['Disposition-Notification-To'], 'ReadReceipt CakePHP '); + $this->assertIdentical($headers['Return-Path'], 'ReturnPath CakePHP '); + $this->assertIdentical($headers['To'], 'To CakePHP , To2 CakePHP '); + $this->assertIdentical($headers['Cc'], 'Cc CakePHP , Cc2 CakePHP '); + $this->assertIdentical($headers['Bcc'], 'Bcc CakePHP , Bcc2 CakePHP '); + } + +/** + * testMessageId method + * + * @return void + */ + public function testMessageId() { + $this->CakeEmail->messageId(true); + $result = $this->CakeEmail->getHeaders(); + $this->assertTrue(isset($result['Message-ID'])); + + $this->CakeEmail->messageId(false); + $result = $this->CakeEmail->getHeaders(); + $this->assertFalse(isset($result['Message-ID'])); + + $result = $this->CakeEmail->messageId(''); + $this->assertIdentical($this->CakeEmail, $result); + $result = $this->CakeEmail->getHeaders(); + $this->assertIdentical($result['Message-ID'], ''); + } + +/** + * testMessageIdInvalid method + * + * @return void + * @expectedException SocketException + */ + public function testMessageIdInvalid() { + $this->CakeEmail->messageId('my-email@localhost'); + } + +/** + * testSubject method + * + * @return void + */ + public function testSubject() { + $this->CakeEmail->subject('You have a new message.'); + $this->assertIdentical($this->CakeEmail->subject(), 'You have a new message.'); + + $this->CakeEmail->subject(1); + $this->assertIdentical($this->CakeEmail->subject(), '1'); + + $result = $this->CakeEmail->subject(array('something')); + $this->assertIdentical($this->CakeEmail->subject(), 'Array'); + $this->assertIdentical($this->CakeEmail, $result); + + $this->CakeEmail->subject('هذه رسالة بعنوان طويل مرسل للمستلم'); + $expected = '=?UTF-8?B?2YfYsNmHINix2LPYp9mE2Kkg2KjYudmG2YjYp9mGINi32YjZitmEINmF2LE=?=' . "\r\n" . ' =?UTF-8?B?2LPZhCDZhNmE2YXYs9iq2YTZhQ==?='; + $this->assertIdentical($this->CakeEmail->subject(), $expected); + } + +/** + * testHeaders method + * + * @return void + */ + public function testHeaders() { + $this->CakeEmail->messageId(false); + $this->CakeEmail->setHeaders(array('X-Something' => 'nice')); + $expected = array( + 'X-Something' => 'nice', + 'X-Mailer' => 'CakePHP Email', + 'Date' => date(DATE_RFC2822), + 'MIME-Version' => '1.0', + 'Content-Type' => 'text/plain; charset=UTF-8', + 'Content-Transfer-Encoding' => '7bit' + ); + $this->assertIdentical($this->CakeEmail->getHeaders(), $expected); + + $this->CakeEmail->addHeaders(array('X-Something' => 'very nice', 'X-Other' => 'cool')); + $expected = array( + 'X-Something' => 'very nice', + 'X-Other' => 'cool', + 'X-Mailer' => 'CakePHP Email', + 'Date' => date(DATE_RFC2822), + 'MIME-Version' => '1.0', + 'Content-Type' => 'text/plain; charset=UTF-8', + 'Content-Transfer-Encoding' => '7bit' + ); + $this->assertIdentical($this->CakeEmail->getHeaders(), $expected); + + $this->CakeEmail->from('cake@cakephp.org'); + $this->assertIdentical($this->CakeEmail->getHeaders(), $expected); + + $expected = array( + 'From' => 'cake@cakephp.org', + 'X-Something' => 'very nice', + 'X-Other' => 'cool', + 'X-Mailer' => 'CakePHP Email', + 'Date' => date(DATE_RFC2822), + 'MIME-Version' => '1.0', + 'Content-Type' => 'text/plain; charset=UTF-8', + 'Content-Transfer-Encoding' => '7bit' + ); + $this->assertIdentical($this->CakeEmail->getHeaders(array('from' => true)), $expected); + + $this->CakeEmail->from('cake@cakephp.org', 'CakePHP'); + $expected['From'] = 'CakePHP '; + $this->assertIdentical($this->CakeEmail->getHeaders(array('from' => true)), $expected); + + $this->CakeEmail->to(array('cake@cakephp.org', 'php@cakephp.org' => 'CakePHP')); + $expected = array( + 'From' => 'CakePHP ', + 'To' => 'cake@cakephp.org, CakePHP ', + 'X-Something' => 'very nice', + 'X-Other' => 'cool', + 'X-Mailer' => 'CakePHP Email', + 'Date' => date(DATE_RFC2822), + 'MIME-Version' => '1.0', + 'Content-Type' => 'text/plain; charset=UTF-8', + 'Content-Transfer-Encoding' => '7bit' + ); + $this->assertIdentical($this->CakeEmail->getHeaders(array('from' => true, 'to' => true)), $expected); + } + +/** + * testTemplate method + * + * @return void + */ + public function testTemplate() { + $this->CakeEmail->template('template', 'layout'); + $expected = array('template' => 'template', 'layout' => 'layout'); + $this->assertIdentical($this->CakeEmail->template(), $expected); + + $this->CakeEmail->template('new_template'); + $expected = array('template' => 'new_template', 'layout' => 'layout'); + $this->assertIdentical($this->CakeEmail->template(), $expected); + + $this->CakeEmail->template('template', null); + $expected = array('template' => 'template', 'layout' => null); + $this->assertIdentical($this->CakeEmail->template(), $expected); + + $this->CakeEmail->template(null, null); + $expected = array('template' => null, 'layout' => null); + $this->assertIdentical($this->CakeEmail->template(), $expected); + } + +/** + * testViewVars method + * + * @return void + */ + public function testViewVars() { + $this->assertIdentical($this->CakeEmail->viewVars(), array()); + + $this->CakeEmail->viewVars(array('value' => 12345)); + $this->assertIdentical($this->CakeEmail->viewVars(), array('value' => 12345)); + + $this->CakeEmail->viewVars(array('name' => 'CakePHP')); + $this->assertIdentical($this->CakeEmail->viewVars(), array('value' => 12345, 'name' => 'CakePHP')); + + $this->CakeEmail->viewVars(array('value' => 4567)); + $this->assertIdentical($this->CakeEmail->viewVars(), array('value' => 4567, 'name' => 'CakePHP')); + } + +/** + * testAttachments method + * + * @return void + */ + public function testAttachments() { + $this->CakeEmail->attachments(CAKE . 'basics.php'); + $expected = array('basics.php' => array('file' => CAKE . 'basics.php', 'mimetype' => 'application/octet-stream')); + $this->assertIdentical($this->CakeEmail->attachments(), $expected); + + $this->CakeEmail->attachments(array()); + $this->assertIdentical($this->CakeEmail->attachments(), array()); + + $this->CakeEmail->attachments(array(array('file' => CAKE . 'basics.php', 'mimetype' => 'text/plain'))); + $this->CakeEmail->addAttachments(CAKE . 'bootstrap.php'); + $this->CakeEmail->addAttachments(array(CAKE . 'bootstrap.php')); + $this->CakeEmail->addAttachments(array('other.txt' => CAKE . 'bootstrap.php', 'license' => CAKE . 'LICENSE.txt')); + $expected = array( + 'basics.php' => array('file' => CAKE . 'basics.php', 'mimetype' => 'text/plain'), + 'bootstrap.php' => array('file' => CAKE . 'bootstrap.php', 'mimetype' => 'application/octet-stream'), + 'other.txt' => array('file' => CAKE . 'bootstrap.php', 'mimetype' => 'application/octet-stream'), + 'license' => array('file' => CAKE . 'LICENSE.txt', 'mimetype' => 'application/octet-stream') + ); + $this->assertIdentical($this->CakeEmail->attachments(), $expected); + } + +/** + * testTransport method + * + * @return void + */ + public function testTransport() { + $result = $this->CakeEmail->transport('debug'); + $this->assertIdentical($this->CakeEmail, $result); + $this->assertIdentical($this->CakeEmail->transport(), 'debug'); + + $result = $this->CakeEmail->transportClass(); + $this->assertIsA($result, 'DebugTransport'); + } + +/** + * testConfig method + * + * @return void + */ + public function testConfig() { + $this->CakeEmail->transport('debug')->transportClass(); + DebugTransport::$config = array(); + + $config = array('test' => 'ok', 'test2' => true); + $this->CakeEmail->config($config); + $this->assertIdentical(DebugTransport::$config, $config); + $this->assertIdentical($this->CakeEmail->config(), $config); + + $this->CakeEmail->config(array()); + $this->assertIdentical(DebugTransport::$config, array()); + } + +/** + * testSendWithContent method + * + * @return void + */ + public function testSendWithContent() { + $this->CakeEmail->reset(); + $this->CakeEmail->transport('debug'); + DebugTransport::$includeAddresses = false; + + $this->CakeEmail->from('cake@cakephp.org'); + $this->CakeEmail->to(array('you@cakephp.org' => 'You')); + $this->CakeEmail->subject('My title'); + $this->CakeEmail->config(array('empty')); + $result = $this->CakeEmail->send("Here is my body, with multi lines.\nThis is the second line.\r\n\r\nAnd the last."); + + $this->assertTrue($result); + $expected = "Here is my body, with multi lines.\r\nThis is the second line.\r\n\r\nAnd the last.\r\n\r\n"; + $this->assertIdentical(DebugTransport::$lastEmail, $expected); + $this->assertTrue((bool)strpos(DebugTransport::$lastHeader, 'Date: ')); + $this->assertTrue((bool)strpos(DebugTransport::$lastHeader, 'Message-ID: ')); + $this->assertFalse(strpos(DebugTransport::$lastHeader, 'To: ')); + + DebugTransport::$includeAddresses = true; + $this->CakeEmail->send("Other body"); + $this->assertIdentical(DebugTransport::$lastEmail, "Other body\r\n\r\n"); + $this->assertTrue((bool)strpos(DebugTransport::$lastHeader, 'Message-ID: ')); + $this->assertTrue((bool)strpos(DebugTransport::$lastHeader, 'To: ')); + } + +/** + * testSendRender method + * + * @return void + */ + public function testSendRender() { + $this->CakeEmail->reset(); + $this->CakeEmail->transport('debug'); + DebugTransport::$includeAddresses = true; + + $this->CakeEmail->from('cake@cakephp.org'); + $this->CakeEmail->to(array('you@cakephp.org' => 'You')); + $this->CakeEmail->subject('My title'); + $this->CakeEmail->config(array('empty')); + $this->CakeEmail->template('default', 'default'); + $result = $this->CakeEmail->send(); + + $this->assertTrue((bool)strpos(DebugTransport::$lastEmail, 'This email was sent using the CakePHP Framework')); + $this->assertTrue((bool)strpos(DebugTransport::$lastHeader, 'Message-ID: ')); + $this->assertTrue((bool)strpos(DebugTransport::$lastHeader, 'To: ')); + } + +/** + * testSendRenderWithVars method + * + * @return void + */ + public function testSendRenderWithVars() { + $this->CakeEmail->reset(); + $this->CakeEmail->transport('debug'); + DebugTransport::$includeAddresses = true; + + $this->CakeEmail->from('cake@cakephp.org'); + $this->CakeEmail->to(array('you@cakephp.org' => 'You')); + $this->CakeEmail->subject('My title'); + $this->CakeEmail->config(array('empty')); + $this->CakeEmail->template('custom', 'default'); + $this->CakeEmail->viewVars(array('value' => 12345)); + $result = $this->CakeEmail->send(); + + $this->assertTrue((bool)strpos(DebugTransport::$lastEmail, 'Here is your value: 12345')); + } + +/** + * testSendMultipleMIME method + * + * @return void + */ + public function testSendMultipleMIME() { + $this->CakeEmail->reset(); + $this->CakeEmail->transport('debug'); + DebugTransport::$includeAddresses = true; + + $this->CakeEmail->from('cake@cakephp.org'); + $this->CakeEmail->to(array('you@cakephp.org' => 'You')); + $this->CakeEmail->subject('My title'); + $this->CakeEmail->template('custom', 'default'); + $this->CakeEmail->config(array()); + $this->CakeEmail->viewVars(array('value' => 12345)); + $this->CakeEmail->emailFormat('both'); + $result = $this->CakeEmail->send(); + + $message = $this->CakeEmail->message(); + $boundary = $this->CakeEmail->getBoundary(); + $this->assertFalse(empty($boundary)); + $this->assertFalse(in_array('--' . $boundary, $message)); + $this->assertFalse(in_array('--' . $boundary . '--', $message)); + $this->assertTrue(in_array('--alt-' . $boundary, $message)); + $this->assertTrue(in_array('--alt-' . $boundary . '--', $message)); + + $this->CakeEmail->attachments(array('fake.php' => __FILE__)); + $this->CakeEmail->send(); + + $message = $this->CakeEmail->message(); + $boundary = $this->CakeEmail->getBoundary(); + $this->assertFalse(empty($boundary)); + $this->assertTrue(in_array('--' . $boundary, $message)); + $this->assertTrue(in_array('--' . $boundary . '--', $message)); + $this->assertTrue(in_array('--alt-' . $boundary, $message)); + $this->assertTrue(in_array('--alt-' . $boundary . '--', $message)); + } + +/** + * testSendAttachment method + * + * @return void + */ + public function testSendAttachment() { + $this->CakeEmail->reset(); + $this->CakeEmail->transport('debug'); + DebugTransport::$includeAddresses = false; + + $this->CakeEmail->from('cake@cakephp.org'); + $this->CakeEmail->to(array('you@cakephp.org' => 'You')); + $this->CakeEmail->subject('My title'); + $this->CakeEmail->config(array()); + $this->CakeEmail->attachments(array(CAKE . 'basics.php')); + $this->CakeEmail->send('body'); + $this->assertTrue((bool)strpos(DebugTransport::$lastEmail, "Content-Type: application/octet-stream\r\nContent-Transfer-Encoding: base64\r\nContent-Disposition: attachment; filename=\"basics.php\"")); + + $this->CakeEmail->attachments(array('my.file.txt' => CAKE . 'basics.php')); + $this->CakeEmail->send('body'); + $this->assertTrue((bool)strpos(DebugTransport::$lastEmail, "Content-Type: application/octet-stream\r\nContent-Transfer-Encoding: base64\r\nContent-Disposition: attachment; filename=\"my.file.txt\"")); + + $this->CakeEmail->attachments(array('file.txt' => array('file' => CAKE . 'basics.php', 'mimetype' => 'text/plain'))); + $this->CakeEmail->send('body'); + $this->assertTrue((bool)strpos(DebugTransport::$lastEmail, "Content-Type: text/plain\r\nContent-Transfer-Encoding: base64\r\nContent-Disposition: attachment; filename=\"file.txt\"")); + + $this->CakeEmail->attachments(array('file.txt' => array('file' => CAKE . 'basics.php', 'mimetype' => 'text/plain', 'contentId' => 'a1b1c1'))); + $this->CakeEmail->send('body'); + $this->assertTrue((bool)strpos(DebugTransport::$lastEmail, "Content-Type: text/plain\r\nContent-Transfer-Encoding: base64\r\nContent-ID: \r\nContent-Disposition: inline; filename=\"file.txt\"")); + } + +/** + * testDeliver method + * + * @return void + */ + public function testDeliver() { + $instance = CakeEmail::deliver('all@cakephp.org', 'About', 'Everything ok', array('from' => 'root@cakephp.org'), false); + $this->assertIsA($instance, 'CakeEmail'); + $this->assertIdentical($instance->to(), array('all@cakephp.org' => 'all@cakephp.org')); + $this->assertIdentical($instance->subject(), 'About'); + $this->assertIdentical($instance->from(), array('root@cakephp.org' => 'root@cakephp.org')); + + $config = array( + 'from' => 'cake@cakephp.org', + 'to' => 'debug@cakephp.org', + 'subject' => 'Update ok', + 'template' => 'custom', + 'layout' => 'custom_layout', + 'viewVars' => array('value' => 123), + 'cc' => array('cake@cakephp.org' => 'Myself') + ); + $instance = CakeEmail::deliver(null, null, array('name' => 'CakePHP'), $config, false); + $this->assertIdentical($instance->from(), array('cake@cakephp.org' => 'cake@cakephp.org')); + $this->assertIdentical($instance->to(), array('debug@cakephp.org' => 'debug@cakephp.org')); + $this->assertIdentical($instance->subject(), 'Update ok'); + $this->assertIdentical($instance->template(), array('template' => 'custom', 'layout' => 'custom_layout')); + $this->assertIdentical($instance->viewVars(), array('value' => 123, 'name' => 'CakePHP')); + $this->assertIdentical($instance->cc(), array('cake@cakephp.org' => 'Myself')); + } + +/** + * testMessage method + * + * @return void + */ + public function testMessage() { + $this->CakeEmail->reset(); + $this->CakeEmail->transport('debug'); + DebugTransport::$includeAddresses = true; + + $this->CakeEmail->from('cake@cakephp.org'); + $this->CakeEmail->to(array('you@cakephp.org' => 'You')); + $this->CakeEmail->subject('My title'); + $this->CakeEmail->config(array('empty')); + $this->CakeEmail->template('default', 'default'); + $this->CakeEmail->emailFormat('both'); + $result = $this->CakeEmail->send(); + + $expected = '

This email was sent using the CakePHP Framework

'; + $this->assertTrue((bool)strpos($this->CakeEmail->message(CakeEmail::MESSAGE_HTML), $expected)); + + $expected = 'This email was sent using the CakePHP Framework, http://cakephp.org.'; + $this->assertTrue((bool)strpos($this->CakeEmail->message(CakeEmail::MESSAGE_TEXT), $expected)); + + $message = $this->CakeEmail->message(); + $this->assertTrue(in_array('Content-Type: text/plain; charset=UTF-8', $message)); + $this->assertTrue(in_array('Content-Type: text/html; charset=UTF-8', $message)); + } + +/** + * testReset method + * + * @return void + */ + public function testReset() { + $this->CakeEmail->to('cake@cakephp.org'); + $this->assertIdentical($this->CakeEmail->to(), array('cake@cakephp.org' => 'cake@cakephp.org')); + + $this->CakeEmail->reset(); + $this->assertIdentical($this->CakeEmail->to(), array()); + } + +/** + * testWrap method + * + * @return void + */ + public function testWrap() { + $text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ac turpis orci, non commodo odio. Morbi nibh nisi, vehicula pellentesque accumsan amet.'; + $result = $this->CakeEmail->wrap($text); + $expected = array( + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ac turpis orci,', + 'non commodo odio. Morbi nibh nisi, vehicula pellentesque accumsan amet.', + '' + ); + $this->assertIdentical($result, $expected); + + $text = 'Lorem ipsum dolor sit amet, consectetur < adipiscing elit. Donec ac turpis orci, non commodo odio. Morbi nibh nisi, vehicula > pellentesque accumsan amet.'; + $result = $this->CakeEmail->wrap($text); + $expected = array( + 'Lorem ipsum dolor sit amet, consectetur < adipiscing elit. Donec ac turpis', + 'orci, non commodo odio. Morbi nibh nisi, vehicula > pellentesque accumsan', + 'amet.', + '' + ); + $this->assertIdentical($result, $expected); + + $text = '

Lorem ipsum dolor sit amet,
consectetur adipiscing elit.
Donec ac turpis orci, non commodo odio.
Morbi nibh nisi, vehicula pellentesque accumsan amet.


'; + $result = $this->CakeEmail->wrap($text); + $expected = array( + '

Lorem ipsum dolor sit amet,
consectetur adipiscing elit.
Donec ac', + 'turpis orci, non commodo odio.
Morbi nibh nisi, vehicula', + 'pellentesque accumsan amet.


', + '' + ); + $this->assertIdentical($result, $expected); + + $text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ac turpis orci, non commodo odio. Morbi nibh nisi, vehicula pellentesque accumsan amet.'; + $result = $this->CakeEmail->wrap($text); + $expected = array( + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ac', + 'turpis orci, non commodo odio. Morbi nibh', + 'nisi, vehicula pellentesque accumsan amet.', + '' + ); + $this->assertIdentical($result, $expected); + + $text = 'Lorem ipsum ok'; + $result = $this->CakeEmail->wrap($text); + $expected = array( + 'Lorem ipsum', + '', + 'ok', + '' + ); + $this->assertIdentical($result, $expected); + + $text = 'Lorem ipsum withonewordverybigMorethanthelineshouldsizeofrfcspecificationbyieeeavailableonieeesite ok.'; + $result = $this->CakeEmail->wrap($text); + $expected = array( + 'Lorem ipsum', + 'withonewordverybigMorethanthelineshouldsizeofrfcspecificationbyieeeavailableonieeesite', + 'ok.', + '' + ); + $this->assertIdentical($result, $expected); + } + +} diff --git a/lib/Cake/tests/Case/Network/CakeSocketTest.php b/lib/Cake/tests/Case/Network/CakeSocketTest.php index f735c9d39..7438531cd 100644 --- a/lib/Cake/tests/Case/Network/CakeSocketTest.php +++ b/lib/Cake/tests/Case/Network/CakeSocketTest.php @@ -170,17 +170,26 @@ class CakeSocketTest extends CakeTestCase { $this->Socket->connect(); $this->assertEqual($this->Socket->read(26), null); - $config = array('host' => '127.0.0.1', 'timeout' => 0.5); - $this->Socket = new CakeSocket($config); - $this->assertTrue($this->Socket->connect()); - $this->assertFalse($this->Socket->read(1024 * 1024)); - $this->assertEqual($this->Socket->lastError(), '2: ' . __d('cake_dev', 'Connection timed out')); - - $config = array('host' => 'cakephp.org', 'port' => 80, 'timeout' => 20); + $config = array('host' => 'google.com', 'port' => 80, 'timeout' => 1); $this->Socket = new CakeSocket($config); $this->assertTrue($this->Socket->connect()); $this->assertEqual($this->Socket->read(26), null); - $this->assertEqual($this->Socket->lastError(), null); + $this->assertEqual($this->Socket->lastError(), '2: ' . __d('cake_dev', 'Connection timed out')); + } + +/** + * testTimeOutConnection method + * + * @return void + */ + function testTimeOutConnection() { + $config = array('host' => '127.0.0.1', 'timeout' => 0.5); + $this->Socket = new CakeSocket($config); + $this->assertTrue($this->Socket->connect()); + + $config = array('host' => '127.0.0.1', 'timeout' => 0.00001); + $this->assertFalse($this->Socket->read(1024 * 1024)); + $this->assertEqual($this->Socket->lastError(), '2: ' . __d('cake_dev', 'Connection timed out')); } /** diff --git a/lib/Cake/tests/Case/Network/Email/SmtpTransportTest.php b/lib/Cake/tests/Case/Network/Email/SmtpTransportTest.php new file mode 100644 index 000000000..49477968b --- /dev/null +++ b/lib/Cake/tests/Case/Network/Email/SmtpTransportTest.php @@ -0,0 +1,261 @@ + + * Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice + * + * @copyright Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests + * @package cake.tests.cases.libs.email + * @since CakePHP(tm) v 2.0.0 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +App::uses('CakeEmail', 'Network'); +App::uses('AbstractTransport', 'Network/Email'); +App::uses('SmtpTransport', 'Network/Email'); + +/** + * Help to test SmtpTransport + * + */ +class SmtpTestTransport extends SmtpTransport { + +/** + * Helper to change the socket + * + * @param object $socket + * @return void + */ + public function setSocket(CakeSocket $socket) { + $this->_socket = $socket; + } + +/** + * Helper to change the CakeEmail + * + * @param object $cakeEmail + * @return void + */ + public function setCakeEmail($cakeEmail) { + $this->_cakeEmail = $cakeEmail; + } + +/** + * Disabled the socket change + * + * @return void + */ + protected function _generateSocket() { + return; + } + +/** + * Magic function to call protected methods + * + * @param string $method + * @param string $args + * @return mixed + */ + public function __call($method, $args) { + $method = '_' . $method; + return $this->$method(); + } + +} + +/** + * Test case + * + */ +class StmpProtocolTest extends CakeTestCase { + +/** + * Setup + * + * @return void + */ + public function setUp() { + if (!class_exists('MockSocket')) { + $this->getMock('CakeSocket', array('read', 'write', 'connect'), array(), 'MockSocket'); + } + $this->socket = new MockSocket(); + + $this->SmtpTransport = new SmtpTestTransport(); + $this->SmtpTransport->setSocket($this->socket); + $this->SmtpTransport->config(); + } + +/** + * testConnectEhlo method + * + * @return void + */ + public function testConnectEhlo() { + $this->socket->expects($this->any())->method('connect')->will($this->returnValue(true)); + $this->socket->expects($this->at(0))->method('read')->will($this->returnValue(false)); + $this->socket->expects($this->at(1))->method('read')->will($this->returnValue("220 Welcome message\r\n")); + $this->socket->expects($this->at(2))->method('write')->with("EHLO localhost\r\n"); + $this->socket->expects($this->at(3))->method('read')->will($this->returnValue(false)); + $this->socket->expects($this->at(4))->method('read')->will($this->returnValue("250 Accepted\r\n")); + $this->SmtpTransport->connect(); + } + +/** + * testConnectHelo method + * + * @return void + */ + public function testConnectHelo() { + $this->socket->expects($this->any())->method('connect')->will($this->returnValue(true)); + $this->socket->expects($this->at(0))->method('read')->will($this->returnValue(false)); + $this->socket->expects($this->at(1))->method('read')->will($this->returnValue("220 Welcome message\r\n")); + $this->socket->expects($this->at(2))->method('write')->with("EHLO localhost\r\n"); + $this->socket->expects($this->at(3))->method('read')->will($this->returnValue(false)); + $this->socket->expects($this->at(4))->method('read')->will($this->returnValue("200 Not Accepted\r\n")); + $this->socket->expects($this->at(5))->method('write')->with("HELO localhost\r\n"); + $this->socket->expects($this->at(6))->method('read')->will($this->returnValue(false)); + $this->socket->expects($this->at(7))->method('read')->will($this->returnValue("250 Accepted\r\n")); + $this->SmtpTransport->connect(); + } + +/** + * testConnectFail method + * + * @expectedException Exception + * @return void + */ + public function testConnetFail() { + $this->socket->expects($this->any())->method('connect')->will($this->returnValue(true)); + $this->socket->expects($this->at(0))->method('read')->will($this->returnValue(false)); + $this->socket->expects($this->at(1))->method('read')->will($this->returnValue("220 Welcome message\r\n")); + $this->socket->expects($this->at(2))->method('write')->with("EHLO localhost\r\n"); + $this->socket->expects($this->at(3))->method('read')->will($this->returnValue(false)); + $this->socket->expects($this->at(4))->method('read')->will($this->returnValue("200 Not Accepted\r\n")); + $this->socket->expects($this->at(5))->method('write')->with("HELO localhost\r\n"); + $this->socket->expects($this->at(6))->method('read')->will($this->returnValue(false)); + $this->socket->expects($this->at(7))->method('read')->will($this->returnValue("200 Not Accepted\r\n")); + $this->SmtpTransport->connect(); + } + +/** + * testAuth method + * + * @return void + */ + public function testAuth() { + $this->socket->expects($this->at(0))->method('write')->with("AUTH LOGIN\r\n"); + $this->socket->expects($this->at(1))->method('read')->will($this->returnValue(false)); + $this->socket->expects($this->at(2))->method('read')->will($this->returnValue("334 Login\r\n")); + $this->socket->expects($this->at(3))->method('write')->with("bWFyaw==\r\n"); + $this->socket->expects($this->at(4))->method('read')->will($this->returnValue(false)); + $this->socket->expects($this->at(5))->method('read')->will($this->returnValue("334 Pass\r\n")); + $this->socket->expects($this->at(6))->method('write')->with("c3Rvcnk=\r\n"); + $this->socket->expects($this->at(7))->method('read')->will($this->returnValue(false)); + $this->socket->expects($this->at(8))->method('read')->will($this->returnValue("235 OK\r\n")); + $this->SmtpTransport->config(array('username' => 'mark', 'password' => 'story')); + $this->SmtpTransport->auth(); + } + +/** + * testAuthNoAuth method + * + * @return void + */ + public function testAuthNoAuth() { + $this->socket->expects($this->never())->method('write')->with("AUTH LOGIN\r\n"); + $this->SmtpTransport->config(array('username' => null, 'password' => null)); + $this->SmtpTransport->auth(); + } + +/** + * testRcpt method + * + * @return void + */ + public function testRcpt() { + $email = new CakeEmail(); + $email->from('noreply@cakephp.org', 'CakePHP Test'); + $email->to('cake@cakephp.org', 'CakePHP'); + $email->bcc('phpnut@cakephp.org'); + $email->cc(array('mark@cakephp.org' => 'Mark Story', 'juan@cakephp.org' => 'Juan Basso')); + + $this->socket->expects($this->at(0))->method('write')->with("MAIL FROM:\r\n"); + $this->socket->expects($this->at(1))->method('read')->will($this->returnValue(false)); + $this->socket->expects($this->at(2))->method('read')->will($this->returnValue("250 OK\r\n")); + $this->socket->expects($this->at(3))->method('write')->with("RCPT TO:\r\n"); + $this->socket->expects($this->at(4))->method('read')->will($this->returnValue(false)); + $this->socket->expects($this->at(5))->method('read')->will($this->returnValue("250 OK\r\n")); + $this->socket->expects($this->at(6))->method('write')->with("RCPT TO:\r\n"); + $this->socket->expects($this->at(7))->method('read')->will($this->returnValue(false)); + $this->socket->expects($this->at(8))->method('read')->will($this->returnValue("250 OK\r\n")); + $this->socket->expects($this->at(9))->method('write')->with("RCPT TO:\r\n"); + $this->socket->expects($this->at(10))->method('read')->will($this->returnValue(false)); + $this->socket->expects($this->at(11))->method('read')->will($this->returnValue("250 OK\r\n")); + $this->socket->expects($this->at(12))->method('write')->with("RCPT TO:\r\n"); + $this->socket->expects($this->at(13))->method('read')->will($this->returnValue(false)); + $this->socket->expects($this->at(14))->method('read')->will($this->returnValue("250 OK\r\n")); + + $this->SmtpTransport->setCakeEmail($email); + $this->SmtpTransport->sendRcpt(); + } + +/** + * testSendData method + * + * @return void + */ + public function testSendData() { + $this->getMock('CakeEmail', array('message'), array(), 'TestCakeEmail'); + $email = new TestCakeEmail(); + $email->from('noreply@cakephp.org', 'CakePHP Test'); + $email->to('cake@cakephp.org', 'CakePHP'); + $email->cc(array('mark@cakephp.org' => 'Mark Story', 'juan@cakephp.org' => 'Juan Basso')); + $email->bcc('phpnut@cakephp.org'); + $email->messageID('<4d9946cf-0a44-4907-88fe-1d0ccbdd56cb@localhost>'); + $email->subject('Testing SMTP'); + $email->expects($this->any())->method('message')->will($this->returnValue(array('First Line', 'Second Line', ''))); + + $data = "From: CakePHP Test \r\n"; + $data .= "To: CakePHP \r\n"; + $data .= "Cc: Mark Story , Juan Basso \r\n"; + $data .= "Bcc: phpnut@cakephp.org\r\n"; + $data .= "X-Mailer: CakePHP Email Component\r\n"; + $data .= "Date: " . date(DATE_RFC2822) . "\r\n"; + $data .= "Message-ID: <4d9946cf-0a44-4907-88fe-1d0ccbdd56cb@localhost>\r\n"; + $data .= "Subject: Testing SMTP\r\n"; + $data .= "Content-Type: text/plain; charset=UTF-8\r\n"; + $data .= "Content-Transfer-Encoding: 7bit\r\n"; + $data .= "\r\n"; + $data .= "First Line\r\n"; + $data .= "Second Line\r\n"; + $data .= "\r\n"; + $data .= "\r\n\r\n.\r\n"; + + $this->socket->expects($this->at(0))->method('write')->with("DATA\r\n"); + $this->socket->expects($this->at(1))->method('read')->will($this->returnValue(false)); + $this->socket->expects($this->at(2))->method('read')->will($this->returnValue("354 OK\r\n")); + $this->socket->expects($this->at(3))->method('write')->with($data); + $this->socket->expects($this->at(4))->method('read')->will($this->returnValue(false)); + $this->socket->expects($this->at(5))->method('read')->will($this->returnValue("250 OK\r\n")); + + $this->SmtpTransport->setCakeEmail($email); + $this->SmtpTransport->sendData(); + } + +/** + * testQuit method + * + * @return void + */ + public function testQuit() { + $this->socket->expects($this->at(0))->method('write')->with("QUIT\r\n"); + $this->SmtpTransport->disconnect(); + } + +} \ No newline at end of file diff --git a/lib/Cake/tests/Case/Utility/FileTest.php b/lib/Cake/tests/Case/Utility/FileTest.php index 5059816f3..8fe7fd0e4 100644 --- a/lib/Cake/tests/Case/Utility/FileTest.php +++ b/lib/Cake/tests/Case/Utility/FileTest.php @@ -17,6 +17,7 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ App::uses('File', 'Utility'); +App::uses('Folder', 'Utility'); /** * FileTest class @@ -487,4 +488,4 @@ class FileTest extends CakeTestCase { } return false; } -} \ No newline at end of file +} diff --git a/lib/Cake/tests/Case/View/Helper/FormHelperTest.php b/lib/Cake/tests/Case/View/Helper/FormHelperTest.php index ce553c3a3..a26a8fb4d 100644 --- a/lib/Cake/tests/Case/View/Helper/FormHelperTest.php +++ b/lib/Cake/tests/Case/View/Helper/FormHelperTest.php @@ -821,7 +821,7 @@ class FormHelperTest extends CakeTestCase { function testFormSecurityFields() { $key = 'testKey'; $fields = array('Model.password', 'Model.username', 'Model.valid' => '0'); - + $this->Form->request['_Token'] = array('key' => $key); $result = $this->Form->secure($fields); @@ -1292,7 +1292,7 @@ class FormHelperTest extends CakeTestCase { * @return void */ function testPasswordValidation() { - $this->Form->validationErrors['Contact']['password'] = 'Please provide a password'; + $this->Form->validationErrors['Contact']['password'] = array('Please provide a password'); $result = $this->Form->input('Contact.password'); $expected = array( 'div' => array('class' => 'input password error'), @@ -1345,7 +1345,7 @@ class FormHelperTest extends CakeTestCase { ); $this->assertTags($result, $expected); - $expected = array('OpenidUrl' => array('openid_not_registered' => true)); + $expected = array('OpenidUrl' => array('openid_not_registered' => array(true))); $this->assertEqual($this->Form->validationErrors, $expected); $result = $this->Form->error( @@ -1389,8 +1389,8 @@ class FormHelperTest extends CakeTestCase { $this->assertTags($result, $expected); $expected = array( - 'ValidateUser' => array('email' => true), - 'ValidateProfile' => array('full_name' => true, 'city' => true) + 'ValidateUser' => array('email' => array(true)), + 'ValidateProfile' => array('full_name' => array(true), 'city' => array(true)) ); $this->assertEqual($this->Form->validationErrors, $expected); @@ -1434,9 +1434,9 @@ class FormHelperTest extends CakeTestCase { $this->assertTags($result, $expected); $expected = array( - 'ValidateUser' => array('email' => true), - 'ValidateProfile' => array('full_name' => true, 'city' => true), - 'ValidateItem' => array('description' => true) + 'ValidateUser' => array('email' => array(true)), + 'ValidateProfile' => array('full_name' => array(true), 'city' => array(true)), + 'ValidateItem' => array('description' => array(true)) ); $this->assertEqual($this->Form->validationErrors, $expected); @@ -1455,7 +1455,7 @@ class FormHelperTest extends CakeTestCase { */ function testFormValidationMultiRecord() { $this->Form->validationErrors['Contact'] = array(2 => array( - 'name' => 'This field cannot be left blank' + 'name' => array('This field cannot be left blank') )); $result = $this->Form->input('Contact.2.name'); $expected = array( @@ -1473,25 +1473,6 @@ class FormHelperTest extends CakeTestCase { '/div' ); $this->assertTags($result, $expected); - - $this->Form->validationErrors['UserForm'] = array( - 'OpenidUrl' => array('url' => 'You must provide a URL' - )); - $this->Form->create('UserForm'); - $result = $this->Form->input('OpenidUrl.url'); - $expected = array( - 'div' => array('class'), - 'label' => array('for'), - 'preg:/[^<]+/', - '/label', - 'input' => array( - 'type' => 'text', 'name', 'id', 'class' => 'form-error' - ), - array('div' => array('class' => 'error-message')), - 'You must provide a URL', - '/div', - '/div' - ); } /** @@ -1504,9 +1485,9 @@ class FormHelperTest extends CakeTestCase { */ function testMultipleInputValidation() { $this->Form->create(); - $this->Form->validationErrors['Address'][0]['title'] = 'This field cannot be empty'; - $this->Form->validationErrors['Address'][0]['first_name'] = 'This field cannot be empty'; - $this->Form->validationErrors['Address'][1]['last_name'] = 'You must have a last name'; + $this->Form->validationErrors['Address'][0]['title'] = array('This field cannot be empty'); + $this->Form->validationErrors['Address'][0]['first_name'] = array('This field cannot be empty'); + $this->Form->validationErrors['Address'][1]['last_name'] = array('You must have a last name'); $result = $this->Form->input('Address.0.title'); $expected = array( @@ -1713,7 +1694,7 @@ class FormHelperTest extends CakeTestCase { unset($this->Form->request->data); - $this->Form->validationErrors['Model']['field'] = 'Badness!'; + $this->Form->validationErrors['Model']['field'] = array('Badness!'); $result = $this->Form->input('Model.field'); $expected = array( 'div' => array('class' => 'input text error'), @@ -1732,7 +1713,7 @@ class FormHelperTest extends CakeTestCase { $this->assertTags($result, $expected); $result = $this->Form->input('Model.field', array( - 'div' => false, 'error' => array('wrap' => 'span') + 'div' => false, 'error' => array('attributes' => array('wrap' => 'span')) )); $expected = array( 'label' => array('for' => 'ModelField'), @@ -1749,7 +1730,7 @@ class FormHelperTest extends CakeTestCase { $this->assertTags($result, $expected); $result = $this->Form->input('Model.field', array( - 'div' => array('tag' => 'span'), 'error' => array('wrap' => false) + 'div' => array('tag' => 'span'), 'error' => array('attributes' => array('wrap' => false)) )); $expected = array( 'span' => array('class' => 'input text error'), @@ -1812,7 +1793,7 @@ class FormHelperTest extends CakeTestCase { ); $this->assertTags($result, $expected); - $this->Form->validationErrors['Model']['field'] = 'minLength'; + $this->Form->validationErrors['Model']['field'] = array('minLength'); $result = $this->Form->input('Model.field', array( 'error' => array( 'minLength' => 'Le login doit contenir au moins 2 caractères', @@ -1832,11 +1813,10 @@ class FormHelperTest extends CakeTestCase { ); $this->assertTags($result, $expected); - $this->Form->validationErrors['Model']['field'] = 'maxLength'; + $this->Form->validationErrors['Model']['field'] = array('maxLength'); $result = $this->Form->input('Model.field', array( 'error' => array( - 'wrap' => 'span', - 'attributes' => array('rel' => 'fake'), + 'attributes' => array('wrap' => 'span', 'rel' => 'fake'), 'minLength' => 'Le login doit contenir au moins 2 caractères', 'maxLength' => 'login too large', ) @@ -2676,18 +2656,18 @@ class FormHelperTest extends CakeTestCase { * @return void */ function testError() { - $this->Form->validationErrors['Model']['field'] = 1; + $this->Form->validationErrors['Model']['field'] = array(1); $result = $this->Form->error('Model.field'); $this->assertTags($result, array('div' => array('class' => 'error-message'), 'Error in field Field', '/div')); $result = $this->Form->error('Model.field', null, array('wrap' => false)); $this->assertEqual($result, 'Error in field Field'); - $this->Form->validationErrors['Model']['field'] = "This field contains invalid input"; + $this->Form->validationErrors['Model']['field'] = array("This field contains invalid input"); $result = $this->Form->error('Model.field', null, array('wrap' => false)); $this->assertEqual($result, 'This field contains invalid input'); - $this->Form->validationErrors['Model']['field'] = "This field contains invalid input"; + $this->Form->validationErrors['Model']['field'] = array("This field contains invalid input"); $result = $this->Form->error('Model.field', null, array('wrap' => 'span')); $this->assertTags($result, array('span' => array('class' => 'error-message'), 'This field contains invalid input', '/span')); @@ -2703,14 +2683,73 @@ class FormHelperTest extends CakeTestCase { $result = $this->Form->error('Model.field', "Badness!", array('wrap' => false, 'escape' => false)); $this->assertEqual($result, 'Badness!'); - $this->Form->validationErrors['Model']['field'] = "email"; - $result = $this->Form->error('Model.field', array('class' => 'field-error', 'email' => 'No good!')); + $this->Form->validationErrors['Model']['field'] = array("email"); + $result = $this->Form->error('Model.field', array('attributes' => array('class' => 'field-error'), 'email' => 'No good!')); $expected = array( 'div' => array('class' => 'field-error'), 'No good!', '/div' ); $this->assertTags($result, $expected); + + $this->Form->validationErrors['Model']['field'] = array('notEmpty', 'email', 'Something else'); + $result = $this->Form->error('Model.field', array( + 'notEmpty' => 'Cannot be empty', + 'email' => 'No good!' + )); + $expected = array( + 'div' => array('class' => 'error-message'), + 'ul' => array(), + 'assertTags($result, $expected); + + /** Testing error messages list options **/ + $this->Form->validationErrors['Model']['field'] = array('notEmpty', 'email'); + + $result = $this->Form->error('Model.field', null, array('listOptions' => 'ol')); + $expected = array( + 'div' => array('class' => 'error-message'), + 'ol' => array(), + 'assertTags($result, $expected); + + $result = $this->Form->error('Model.field', null, array('listOptions' => array('tag' => 'ol'))); + $expected = array( + 'div' => array('class' => 'error-message'), + 'ol' => array(), + 'assertTags($result, $expected); + + $result = $this->Form->error('Model.field', null, array( + 'listOptions' => array( + 'class' => 'ul-class', + 'itemOptions' => array( + 'class' => 'li-class' + ) + ) + )); + $expected = array( + 'div' => array('class' => 'error-message'), + 'ul' => array('class' => 'ul-class'), + array('li' => array('class' => 'li-class')), 'notEmpty', '/li', + array('li' => array('class' => 'li-class')), 'email', '/li', + '/ul', + '/div' + ); + $this->assertTags($result, $expected); } /** @@ -2720,11 +2759,11 @@ class FormHelperTest extends CakeTestCase { */ function testInputErrorEscape() { $this->Form->create('ValidateProfile'); - $this->Form->validationErrors['ValidateProfile']['city'] = 'required
'; - $result = $this->Form->input('city',array('error' => array('escape' => true))); + $this->Form->validationErrors['ValidateProfile']['city'] = array('required
'); + $result = $this->Form->input('city',array('error' => array('attributes' => array('escape' => true)))); $this->assertPattern('/required<br>/', $result); - $result = $this->Form->input('city',array('error' => array('escape' => false))); + $result = $this->Form->input('city',array('error' => array('attributes' => array('escape' => false)))); $this->assertPattern('/required
/', $result); } @@ -3648,7 +3687,7 @@ class FormHelperTest extends CakeTestCase { 'div' => false )); $expected = array( - 'input' => array('type' => 'hidden', 'name' => 'data[Model][tags]', 'value' => '', 'id' => 'ModelTags'), + 'input' => array('type' => 'hidden', 'class' => 'form-error', 'name' => 'data[Model][tags]', 'value' => '', 'id' => 'ModelTags'), array('div' => array('class' => 'checkbox form-error')), array('input' => array('type' => 'checkbox', 'name' => 'data[Model][tags][]', 'value' => '0', 'id' => 'ModelTags0')), array('label' => array('for' => 'ModelTags0')), @@ -3666,7 +3705,7 @@ class FormHelperTest extends CakeTestCase { 'div' => false )); $expected = array( - 'input' => array('type' => 'hidden', 'name' => 'data[Model][tags]', 'value' => '', 'id' => 'ModelTags'), + 'input' => array('type' => 'hidden', 'class' => 'form-error', 'name' => 'data[Model][tags]', 'value' => '', 'id' => 'ModelTags'), array('div' => array('class' => 'mycheckbox form-error')), array('input' => array('type' => 'checkbox', 'name' => 'data[Model][tags][]', 'value' => '0', 'id' => 'ModelTags0')), array('label' => array('for' => 'ModelTags0')), @@ -3861,14 +3900,14 @@ class FormHelperTest extends CakeTestCase { $this->Form->request->data['Model']['field'] = 'myvalue'; $result = $this->Form->checkbox('Model.field', array('id' => 'theID', 'value' => 'myvalue')); $expected = array( - 'input' => array('type' => 'hidden', 'name' => 'data[Model][field]', 'value' => '0', 'id' => 'theID_'), + 'input' => array('type' => 'hidden', 'class' => 'form-error', 'name' => 'data[Model][field]', 'value' => '0', 'id' => 'theID_'), array('input' => array('preg:/[^<]+/', 'value' => 'myvalue', 'id' => 'theID', 'checked' => 'checked', 'class' => 'form-error')) ); $this->assertTags($result, $expected); $result = $this->Form->checkbox('Model.field', array('value' => 'myvalue')); $expected = array( - 'input' => array('type' => 'hidden', 'name' => 'data[Model][field]', 'value' => '0', 'id' => 'ModelField_'), + 'input' => array('type' => 'hidden', 'class' => 'form-error', 'name' => 'data[Model][field]', 'value' => '0', 'id' => 'ModelField_'), array('input' => array('preg:/[^<]+/', 'value' => 'myvalue', 'id' => 'ModelField', 'checked' => 'checked', 'class' => 'form-error')) ); $this->assertTags($result, $expected); @@ -3876,7 +3915,7 @@ class FormHelperTest extends CakeTestCase { $this->Form->request->data['Model']['field'] = ''; $result = $this->Form->checkbox('Model.field', array('id' => 'theID')); $expected = array( - 'input' => array('type' => 'hidden', 'name' => 'data[Model][field]', 'value' => '0', 'id' => 'theID_'), + 'input' => array('type' => 'hidden', 'class' => 'form-error', 'name' => 'data[Model][field]', 'value' => '0', 'id' => 'theID_'), array('input' => array('type' => 'checkbox', 'name' => 'data[Model][field]', 'value' => '1', 'id' => 'theID', 'class' => 'form-error')) ); $this->assertTags($result, $expected); @@ -5277,7 +5316,9 @@ class FormHelperTest extends CakeTestCase { $this->Form->validationErrors['Model']['field'] = 1; $this->Form->request->data['Model']['field'] = 'test'; $result = $this->Form->hidden('Model.field', array('id' => 'theID')); - $this->assertTags($result, array('input' => array('type' => 'hidden', 'name' => 'data[Model][field]', 'id' => 'theID', 'value' => 'test'))); + $this->assertTags($result, array( + 'input' => array('type' => 'hidden', 'class' => 'form-error', 'name' => 'data[Model][field]', 'id' => 'theID', 'value' => 'test')) + ); } /** @@ -6033,7 +6074,7 @@ class FormHelperTest extends CakeTestCase { 'email' => 'nate@example.com' )); $this->Form->request->addParams(array( - 'models' => array('Person'), + 'models' => array('Person'), 'controller' => 'people', 'action' => 'add' )); @@ -6850,11 +6891,11 @@ class FormHelperTest extends CakeTestCase { */ function testMultiRecordFormValidationErrors() { $this->Form->create('ValidateProfile'); - $this->Form->validationErrors['ValidateProfile'][2]['ValidateItem'][1]['name'] = 'Error in field name'; + $this->Form->validationErrors['ValidateProfile'][2]['ValidateItem'][1]['name'] = array('Error in field name'); $result = $this->Form->error('ValidateProfile.2.ValidateItem.1.name'); $this->assertTags($result, array('div' => array('class' => 'error-message'), 'Error in field name', '/div')); - $this->Form->validationErrors['ValidateProfile'][2]['city'] = 'Error in field city'; + $this->Form->validationErrors['ValidateProfile'][2]['city'] = array('Error in field city'); $result = $this->Form->error('ValidateProfile.2.city'); $this->assertTags($result, array('div' => array('class' => 'error-message'), 'Error in field city', '/div')); @@ -6948,7 +6989,7 @@ class FormHelperTest extends CakeTestCase { 'input' => array('type' => 'search', 'name' => 'data[User][query]', 'id' => 'UserQuery', 'value' => 'test') ); $this->assertTags($result, $expected); - + $result = $this->Form->search('User.query', array('type' => 'text', 'value' => 'test')); $expected = array( 'input' => array('type' => 'text', 'name' => 'data[User][query]', 'id' => 'UserQuery', 'value' => 'test') @@ -6957,7 +6998,7 @@ class FormHelperTest extends CakeTestCase { } /** - * + * * @expectedException CakeException * @return void */ diff --git a/lib/Cake/tests/Case/View/Helper/HtmlHelperTest.php b/lib/Cake/tests/Case/View/Helper/HtmlHelperTest.php index 9fd4c390c..d6f0055dd 100644 --- a/lib/Cake/tests/Case/View/Helper/HtmlHelperTest.php +++ b/lib/Cake/tests/Case/View/Helper/HtmlHelperTest.php @@ -17,12 +17,13 @@ * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ +App::uses('Controller', 'Controller'); App::uses('Helper', 'View'); App::uses('AppHelper', 'View/Helper'); -App::uses('ClassRegistry', 'Utility'); -App::uses('Controller', 'Controller'); App::uses('HtmlHelper', 'View/Helper'); App::uses('FomrHelper', 'View/Helper'); +App::uses('ClassRegistry', 'Utility'); +App::uses('Folder', 'Utility'); if (!defined('FULL_BASE_URL')) { define('FULL_BASE_URL', 'http://cakephp.org'); @@ -56,10 +57,10 @@ class TestHtmlHelper extends HtmlHelper { /** * expose a method as public * - * @param string $options - * @param string $exclude - * @param string $insertBefore - * @param string $insertAfter + * @param string $options + * @param string $exclude + * @param string $insertBefore + * @param string $insertAfter * @return void */ function parseAttributes($options, $exclude = null, $insertBefore = ' ', $insertAfter = null) { @@ -639,7 +640,7 @@ class HtmlHelperTest extends CakeTestCase { 'script' => array('type' => 'text/javascript', 'src' => 'js/jquery-1.3.2.js', 'defer' => 'defer', 'encoding' => 'utf-8') ); $this->assertTags($result, $expected); - + $this->View->expects($this->any())->method('addScript') ->with($this->matchesRegularExpression('/script_in_head.js/')); $result = $this->Html->script('script_in_head', array('inline' => false)); @@ -711,7 +712,7 @@ class HtmlHelperTest extends CakeTestCase { ); $this->assertTags($result, $expected); - + $this->View->expects($this->any())->method('addScript') ->with($this->matchesRegularExpression('/window\.foo\s\=\s2;/')); @@ -1342,12 +1343,12 @@ class HtmlHelperTest extends CakeTestCase { $result = $this->Html->para('class-name', '', array('escape' => true)); $this->assertTags($result, array('p' => array('class' => 'class-name'), '<text>', '/p')); } - + /** * testCrumbList method - * + * * @access public - * + * * @return void */ function testCrumbList() { @@ -1435,7 +1436,7 @@ class HtmlHelperTest extends CakeTestCase { $helper = new TestHtmlHelper($this->View); $compact = array('compact', 'checked', 'declare', 'readonly', 'disabled', 'selected', 'defer', 'ismap', 'nohref', 'noshade', 'nowrap', 'multiple', 'noresize'); - + foreach ($compact as $attribute) { foreach (array('true', true, 1, '1', $attribute) as $value) { $attrs = array($attribute => $value); diff --git a/lib/Cake/tests/test_app/View/elements/email/html/custom.ctp b/lib/Cake/tests/test_app/View/emails/html/custom.ctp similarity index 100% rename from lib/Cake/tests/test_app/View/elements/email/html/custom.ctp rename to lib/Cake/tests/test_app/View/emails/html/custom.ctp diff --git a/lib/Cake/tests/test_app/View/elements/email/html/default.ctp b/lib/Cake/tests/test_app/View/emails/html/default.ctp similarity index 100% rename from lib/Cake/tests/test_app/View/elements/email/html/default.ctp rename to lib/Cake/tests/test_app/View/emails/html/default.ctp diff --git a/lib/Cake/tests/test_app/View/elements/email/html/nested_element.ctp b/lib/Cake/tests/test_app/View/emails/html/nested_element.ctp similarity index 100% rename from lib/Cake/tests/test_app/View/elements/email/html/nested_element.ctp rename to lib/Cake/tests/test_app/View/emails/html/nested_element.ctp diff --git a/lib/Cake/tests/test_app/View/elements/email/text/custom.ctp b/lib/Cake/tests/test_app/View/emails/text/custom.ctp similarity index 100% rename from lib/Cake/tests/test_app/View/elements/email/text/custom.ctp rename to lib/Cake/tests/test_app/View/emails/text/custom.ctp diff --git a/lib/Cake/tests/test_app/View/elements/email/text/default.ctp b/lib/Cake/tests/test_app/View/emails/text/default.ctp similarity index 100% rename from lib/Cake/tests/test_app/View/elements/email/text/default.ctp rename to lib/Cake/tests/test_app/View/emails/text/default.ctp diff --git a/lib/Cake/tests/test_app/View/elements/email/text/wide.ctp b/lib/Cake/tests/test_app/View/emails/text/wide.ctp similarity index 100% rename from lib/Cake/tests/test_app/View/elements/email/text/wide.ctp rename to lib/Cake/tests/test_app/View/emails/text/wide.ctp diff --git a/lib/Cake/tests/test_app/View/layouts/email/html/default.ctp b/lib/Cake/tests/test_app/View/layouts/emails/html/default.ctp similarity index 100% rename from lib/Cake/tests/test_app/View/layouts/email/html/default.ctp rename to lib/Cake/tests/test_app/View/layouts/emails/html/default.ctp diff --git a/lib/Cake/tests/test_app/View/layouts/email/html/thin.ctp b/lib/Cake/tests/test_app/View/layouts/emails/html/thin.ctp similarity index 100% rename from lib/Cake/tests/test_app/View/layouts/email/html/thin.ctp rename to lib/Cake/tests/test_app/View/layouts/emails/html/thin.ctp diff --git a/lib/Cake/tests/test_app/View/layouts/email/text/default.ctp b/lib/Cake/tests/test_app/View/layouts/emails/text/default.ctp similarity index 100% rename from lib/Cake/tests/test_app/View/layouts/email/text/default.ctp rename to lib/Cake/tests/test_app/View/layouts/emails/text/default.ctp