Merge branch '2.1' of https://github.com/cakephp/cakephp into 2.1-cookie-response

This commit is contained in:
Thomas Ploch 2012-02-13 09:56:39 +01:00
commit 574b5dcd41
63 changed files with 4433 additions and 2500 deletions

View file

@ -23,7 +23,66 @@
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
// Setup a 'default' cache configuration for use in the application.
/**
* Cache Engine Configuration
* Default settings provided below
*
* File storage engine.
*
* Cache::config('default', array(
* 'engine' => 'File', //[required]
* 'duration'=> 3600, //[optional]
* 'probability'=> 100, //[optional]
* 'path' => CACHE, //[optional] use system tmp directory - remember to use absolute path
* 'prefix' => 'cake_', //[optional] prefix every cache file with this string
* 'lock' => false, //[optional] use file locking
* 'serialize' => true, // [optional]
* 'mask' => 0666, // [optional] permission mask to use when creating cache files
* ));
*
* APC (http://pecl.php.net/package/APC)
*
* Cache::config('default', array(
* 'engine' => 'Apc', //[required]
* 'duration'=> 3600, //[optional]
* 'probability'=> 100, //[optional]
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
* ));
*
* Xcache (http://xcache.lighttpd.net/)
*
* Cache::config('default', array(
* 'engine' => 'Xcache', //[required]
* 'duration'=> 3600, //[optional]
* 'probability'=> 100, //[optional]
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
* 'user' => 'user', //user from xcache.admin.user settings
* 'password' => 'password', //plaintext password (xcache.admin.pass)
* ));
*
* Memcache (http://memcached.org/)
*
* Cache::config('default', array(
* 'engine' => 'Memcache', //[required]
* 'duration'=> 3600, //[optional]
* 'probability'=> 100, //[optional]
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
* 'servers' => array(
* '127.0.0.1:11211' // localhost, default port 11211
* ), //[optional]
* 'persistent' => true, // [optional] set this to false for non-persistent connections
* 'compress' => false, // [optional] compress data in Memcache (slower, but uses less memory)
* ));
*
* Wincache (http://php.net/wincache)
*
* Cache::config('default', array(
* 'engine' => 'Wincache', //[required]
* 'duration'=> 3600, //[optional]
* 'probability'=> 100, //[optional]
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
* ));
*/
Cache::config('default', array('engine' => 'File'));
/**

View file

@ -231,71 +231,13 @@
*/
//date_default_timezone_set('UTC');
/**
*
* Cache Engine Configuration
* Default settings provided below
*
* File storage engine.
*
* Cache::config('default', array(
* 'engine' => 'File', //[required]
* 'duration'=> 3600, //[optional]
* 'probability'=> 100, //[optional]
* 'path' => CACHE, //[optional] use system tmp directory - remember to use absolute path
* 'prefix' => 'cake_', //[optional] prefix every cache file with this string
* 'lock' => false, //[optional] use file locking
* 'serialize' => true, [optional]
* ));
*
* APC (http://pecl.php.net/package/APC)
*
* Cache::config('default', array(
* 'engine' => 'Apc', //[required]
* 'duration'=> 3600, //[optional]
* 'probability'=> 100, //[optional]
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
* ));
*
* Xcache (http://xcache.lighttpd.net/)
*
* Cache::config('default', array(
* 'engine' => 'Xcache', //[required]
* 'duration'=> 3600, //[optional]
* 'probability'=> 100, //[optional]
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
* 'user' => 'user', //user from xcache.admin.user settings
* 'password' => 'password', //plaintext password (xcache.admin.pass)
* ));
*
* Memcache (http://memcached.org/)
*
* Cache::config('default', array(
* 'engine' => 'Memcache', //[required]
* 'duration'=> 3600, //[optional]
* 'probability'=> 100, //[optional]
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
* 'servers' => array(
* '127.0.0.1:11211' // localhost, default port 11211
* ), //[optional]
* 'persistent' => true, // [optional] set this to false for non-persistent connections
* 'compress' => false, // [optional] compress data in Memcache (slower, but uses less memory)
* ));
*
* Wincache (http://php.net/wincache)
*
* Cache::config('default', array(
* 'engine' => 'Wincache', //[required]
* 'duration'=> 3600, //[optional]
* 'probability'=> 100, //[optional]
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
* ));
*/
/**
* Pick the caching engine to use. If APC is enabled use it.
* If running via cli - apc is disabled by default. ensure it's available and enabled in this case
*
* Note: 'default' and other application caches should be configured in app/Config/bootstrap.php.
* Please check the comments in boostrap.php for more info on the cache engines available
* and their setttings.
*/
$engine = 'File';
if (extension_loaded('apc') && function_exists('apc_dec') && (php_sapi_name() !== 'cli' || ini_get('apc.enable_cli'))) {

View file

@ -121,9 +121,9 @@ if (isset($filePresent)):
App::uses('Validation', 'Utility');
if (!Validation::alphaNumeric('cakephp')) {
echo '<p><span class="notice">';
__d('cake_dev', 'PCRE has not been compiled with Unicode support.');
echo '<br/>';
__d('cake_dev', 'Recompile PCRE with Unicode support by adding <code>--enable-unicode-properties</code> when configuring');
echo __d('cake_dev', 'PCRE has not been compiled with Unicode support.');
echo '<br/>';
echo __d('cake_dev', 'Recompile PCRE with Unicode support by adding <code>--enable-unicode-properties</code> when configuring');
echo '</span></p>';
}
?>

View file

@ -126,7 +126,7 @@ class ControllerTask extends BakeTask {
protected function _interactive() {
$this->interactive = true;
$this->hr();
$this->out(__d('cake_console', "Bake Controller\nPath: %s", $this->path));
$this->out(__d('cake_console', "Bake Controller\nPath: %s", $this->getPath()));
$this->hr();
if (empty($this->connection)) {

View file

@ -70,12 +70,19 @@ class ExtractTask extends AppShell {
protected $_tokens = array();
/**
* Extracted strings
* Extracted strings indexed by domain.
*
* @var array
*/
protected $_strings = array();
/**
* Singular strings and their line numbers.
*
* @var array
*/
protected $_lines = array();
/**
* Destination path
*
@ -325,8 +332,10 @@ class ExtractTask extends AppShell {
if ($mapCount == count($strings)) {
extract(array_combine($map, $strings));
$domain = isset($domain) ? $domain : 'default';
$string = isset($plural) ? $singular . "\0" . $plural : $singular;
$this->_strings[$domain][$string][$this->_file][] = $line;
$this->_strings[$domain][] = $string;
$this->_lines[$domain][$singular][$this->_file][] = $line;
} else {
$this->_markerError($this->_file, $line, $functionName, $count);
}
@ -406,7 +415,8 @@ class ExtractTask extends AppShell {
$message = $rule;
}
if ($message) {
$this->_strings[$domain][$message][$file][] = 'validation for field ' . $field;
$this->_strings[$domain][] = $message;
$this->_lines[$domain][$message][$file][] = 'validation for field ' . $field;
}
}
}
@ -419,7 +429,16 @@ class ExtractTask extends AppShell {
*/
protected function _buildFiles() {
foreach ($this->_strings as $domain => $strings) {
foreach ($strings as $string => $files) {
$added = array();
rsort($strings);
foreach ($strings as $i => $string) {
$plural = false;
$singular = $string;
if (strpos($string, "\0") !== false) {
list($singular, $plural) = explode("\0", $string);
}
$files = $this->_lines[$domain][$singular];
$occurrences = array();
foreach ($files as $file => $lines) {
$occurrences[] = $file . ':' . implode(';', $lines);
@ -427,17 +446,21 @@ class ExtractTask extends AppShell {
$occurrences = implode("\n#: ", $occurrences);
$header = '#: ' . str_replace($this->_paths, '', $occurrences) . "\n";
if (strpos($string, "\0") === false) {
if ($plural === false && !empty($added[$singular])) {
continue;
}
if ($plural === false) {
$sentence = "msgid \"{$string}\"\n";
$sentence .= "msgstr \"\"\n\n";
} else {
list($singular, $plural) = explode("\0", $string);
$sentence = "msgid \"{$singular}\"\n";
$sentence .= "msgid_plural \"{$plural}\"\n";
$sentence .= "msgstr[0] \"\"\n";
$sentence .= "msgstr[1] \"\"\n\n";
}
$added[$singular] = true;
$this->_store($domain, $header, $sentence);
if ($domain != 'default' && $this->_merge) {
$this->_store('default', $header, $sentence);

View file

@ -137,7 +137,7 @@ class FixtureTask extends BakeTask {
protected function _interactive() {
$this->DbConfig->interactive = $this->Model->interactive = $this->interactive = true;
$this->hr();
$this->out(__d('cake_console', "Bake Fixture\nPath: %s", $this->path));
$this->out(__d('cake_console', "Bake Fixture\nPath: %s", $this->getPath()));
$this->hr();
if (!isset($this->connection)) {

View file

@ -190,7 +190,7 @@ class ModelTask extends BakeTask {
*/
protected function _interactive() {
$this->hr();
$this->out(__d('cake_console', "Bake Model\nPath: %s", $this->path));
$this->out(__d('cake_console', "Bake Model\nPath: %s", $this->getPath()));
$this->hr();
$this->interactive = true;

View file

@ -94,7 +94,7 @@ class TestTask extends BakeTask {
$this->interactive = true;
$this->hr();
$this->out(__d('cake_console', 'Bake Tests'));
$this->out(__d('cake_console', 'Path: %s', $this->path));
$this->out(__d('cake_console', 'Path: %s', $this->getPath()));
$this->hr();
if ($type) {

View file

@ -195,7 +195,7 @@ class ViewTask extends BakeTask {
*/
protected function _interactive() {
$this->hr();
$this->out(sprintf("Bake View\nPath: %s", $this->path));
$this->out(sprintf("Bake View\nPath: %s", $this->getPath()));
$this->hr();
$this->DbConfig->interactive = $this->Controller->interactive = $this->interactive = true;

View file

@ -108,11 +108,13 @@ abstract class BaseAuthorize {
*/
public function action($request, $path = '/:plugin/:controller/:action') {
$plugin = empty($request['plugin']) ? null : Inflector::camelize($request['plugin']) . '/';
return str_replace(
$path = str_replace(
array(':controller', ':action', ':plugin/'),
array(Inflector::camelize($request['controller']), $request['action'], $plugin),
$this->settings['actionPath'] . $path
);
$path = str_replace('//', '/', $path);
return trim($path, '/');
}
/**

View file

@ -495,7 +495,8 @@ class CookieComponent extends Component {
* @return array Map of key and values
*/
protected function _explode($string) {
if ($string[0] === '{' || $string[0] === '[') {
$first = substr($string, 0, 1);
if ($first === '{' || $first === '[') {
$ret = json_decode($string, true);
return ($ret != null) ? $ret : $string;
}

View file

@ -160,7 +160,10 @@ class RequestHandlerComponent extends Component {
* switched based on the parsed extension or Accept-Type header. For example, if `controller/action.xml`
* is requested, the view path becomes `app/View/Controller/xml/action.ctp`. Also if
* `controller/action` is requested with `Accept-Type: application/xml` in the headers
* the view path will become `app/View/Controller/xml/action.ctp`.
* the view path will become `app/View/Controller/xml/action.ctp`. Layout and template
* types will only switch to mime-types recognized by CakeResponse. If you need to declare
* additional mime-types, you can do so using CakeResponse::type() in your controllers beforeFilter()
* method.
* - If a helper with the same name as the extension exists, it is added to the controller.
* - If the extension is of a type that RequestHandler understands, it will set that
* Content-type in the response header.

View file

@ -860,7 +860,7 @@ class App {
),
'Vendor' => array(
'%s' . 'Vendor' . DS,
VENDORS
dirname(dirname(CAKE)) . DS . 'vendors' . DS,
),
'Plugin' => array(
APP . 'Plugin' . DS,

View file

@ -217,6 +217,7 @@ class ErrorHandler {
$log = LOG_NOTICE;
break;
case E_DEPRECATED:
case E_USER_DEPRECATED:
$error = 'Deprecated';
$log = LOG_NOTICE;
break;

View file

@ -16,14 +16,14 @@
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::uses('AppModel', 'Model');
App::uses('Model', 'Model');
/**
* ACL Node
*
* @package Cake.Model
*/
class AclNode extends AppModel {
class AclNode extends Model {
/**
* Explicitly disable in-memory query caching for ACL models

View file

@ -16,7 +16,6 @@
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::uses('AppModel', 'Model');
App::uses('AclNode', 'Model');
/**

View file

@ -16,7 +16,6 @@
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::uses('AppModel', 'Model');
App::uses('AclNode', 'Model');
/**

View file

@ -745,7 +745,7 @@ class Sqlserver extends DboSource {
*/
protected function _execute($sql, $params = array(), $prepareOptions = array()) {
$this->_lastAffected = false;
if (strncasecmp($sql, 'SELECT', 6) == 0) {
if (strncasecmp($sql, 'SELECT', 6) == 0 || preg_match('/^EXEC(?:UTE)?\s/mi', $sql) > 0) {
$prepareOptions += array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL);
return parent::_execute($sql, $params, $prepareOptions);
}

View file

@ -1966,7 +1966,15 @@ class Model extends Object implements CakeEventListener {
* or 'only' to only validate the records, but not save them.
* - atomic: If true (default), will attempt to save all records in a single transaction.
* Should be set to false if database/table does not support transactions.
* - fieldList: Equivalent to the $fieldList parameter in Model::save()
* - fieldList: Equivalent to the $fieldList parameter in Model::save().
* It should be an associate array with model name as key and array of fields as value. Eg.
* {{{
* array(
* 'SomeModel' => array('field'),
* 'AssociatedModel' => array('field', 'otherfield')
* )
* }}}
* - deep: see saveMany/saveAssociated
*
* @param array $data Record data to save. This can be either a numerically-indexed array (for saving multiple
* records of the same type), or an array indexed by association name.
@ -1986,11 +1994,7 @@ class Model extends Object implements CakeEventListener {
return $this->saveMany($data, $options);
}
if ($options['validate'] === 'only') {
$validatesAssoc = $this->validateAssociated($data, $options);
if (isset($this->validationErrors[$this->alias]) && $this->validationErrors[$this->alias] === false) {
return false;
}
return $validatesAssoc;
return $this->validateAssociated($data, $options);
}
return $this->saveAssociated($data, $options);
}
@ -2005,6 +2009,7 @@ class Model extends Object implements CakeEventListener {
* - atomic: If true (default), will attempt to save all records in a single transaction.
* Should be set to false if database/table does not support transactions.
* - fieldList: Equivalent to the $fieldList parameter in Model::save()
* - deep: If set to true, all associated data will be saved as well.
*
* @param array $data Record data to save. This should be a numerically-indexed array
* @param array $options Options to use when saving record data, See $options above.
@ -2018,7 +2023,7 @@ class Model extends Object implements CakeEventListener {
$data = $this->data;
}
$options = array_merge(array('validate' => 'first', 'atomic' => true), $options);
$options = array_merge(array('validate' => 'first', 'atomic' => true, 'deep' => false), $options);
$this->validationErrors = $validationErrors = array();
if (empty($data) && $options['validate'] !== false) {
@ -2039,12 +2044,21 @@ class Model extends Object implements CakeEventListener {
}
$return = array();
foreach ($data as $key => $record) {
$validates = ($this->create(null) !== null && $this->save($record, $options));
$validates = $this->create(null) !== null;
$saved = false;
if ($validates) {
if ($options['deep']) {
$saved = $this->saveAssociated($record, array_merge($options, array('atomic' => false)));
} else {
$saved = $this->save($record, $options);
}
}
$validates = ($validates && ($saved === true || (is_array($saved) && !in_array(false, $saved, true))));
if (!$validates) {
$validationErrors[$key] = $this->validationErrors;
}
if (!$options['atomic']) {
$return[] = $validates;
$return[$key] = $validates;
} elseif (!$validates) {
break;
}
@ -2072,6 +2086,7 @@ class Model extends Object implements CakeEventListener {
*
* - atomic: If true (default), returns boolean. If false returns array.
* - fieldList: Equivalent to the $fieldList parameter in Model::save()
* - deep: If set to true, all associated data will be validated as well.
*
* @param array $data Record data to validate. This should be a numerically-indexed array
* @param array $options Options to use when validating record data (see above), See also $options of validates().
@ -2081,14 +2096,21 @@ class Model extends Object implements CakeEventListener {
* depending on whether each record validated successfully.
*/
public function validateMany($data, $options = array()) {
$options = array_merge(array('atomic' => true), $options);
$options = array_merge(array('atomic' => true, 'deep' => false), $options);
$this->validationErrors = $validationErrors = $return = array();
foreach ($data as $key => $record) {
$validates = $this->create($record) && $this->validates($options);
if (!$validates) {
$validationErrors[$key] = $this->validationErrors;
if ($options['deep']) {
$validates = $this->validateAssociated($record, $options);
} else {
$validates = $this->create($record) && $this->validates($options);
}
$return[] = $validates;
if ($validates === false || (is_array($validates) && in_array(false, $validates, true))) {
$validationErrors[$key] = $this->validationErrors;
$validates = false;
} else {
$validates = true;
}
$return[$key] = $validates;
}
$this->validationErrors = $validationErrors;
if (!$options['atomic']) {
@ -2109,7 +2131,15 @@ class Model extends Object implements CakeEventListener {
* 'first' to validate *all* records before any are saved(default),
* - `atomic` If true (default), will attempt to save all records in a single transaction.
* Should be set to false if database/table does not support transactions.
* - `fieldList` Equivalent to the $fieldList parameter in Model::save()
* - fieldList: Equivalent to the $fieldList parameter in Model::save().
* It should be an associate array with model name as key and array of fields as value. Eg.
* {{{
* array(
* 'SomeModel' => array('field'),
* 'AssociatedModel' => array('field', 'otherfield')
* )
* }}}
* - deep: If set to true, not only directly associated data is saved, but deeper nested associated data as well.
*
* @param array $data Record data to save. This should be an array indexed by association name.
* @param array $options Options to use when saving record data, See $options above.
@ -2123,7 +2153,7 @@ class Model extends Object implements CakeEventListener {
$data = $this->data;
}
$options = array_merge(array('validate' => 'first', 'atomic' => true), $options);
$options = array_merge(array('validate' => 'first', 'atomic' => true, 'deep' => false), $options);
$this->validationErrors = $validationErrors = array();
if (empty($data) && $options['validate'] !== false) {
@ -2146,13 +2176,26 @@ class Model extends Object implements CakeEventListener {
$validates = true;
foreach ($data as $association => $values) {
if (isset($associations[$association]) && $associations[$association] === 'belongsTo') {
if ($this->{$association}->create(null) !== null && $this->{$association}->save($values, $options)) {
$data[$this->alias][$this->belongsTo[$association]['foreignKey']] = $this->{$association}->id;
$validates = $this->{$association}->create(null) !== null;
$saved = false;
if ($validates) {
if ($options['deep']) {
$saved = $this->{$association}->saveAssociated($values, array_merge($options, array('atomic' => false)));
} else {
$saved = $this->{$association}->save($values, array_merge($options, array('atomic' => false)));
}
$validates = ($saved === true || (is_array($saved) && !in_array(false, $saved, true)));
}
if ($validates) {
if (!empty($data[$this->alias])) {
$data[$this->alias][$this->belongsTo[$association]['foreignKey']] = $this->{$association}->id;
} else {
$data[$this->belongsTo[$association]['foreignKey']] = $this->{$association}->id;
}
} else {
$validationErrors[$association] = $this->{$association}->validationErrors;
$validates = false;
}
$return[$association][] = $validates;
$return[$association] = $validates;
}
}
if ($validates && !($this->create(null) !== null && $this->save($data, $options))) {
@ -2170,11 +2213,20 @@ class Model extends Object implements CakeEventListener {
switch ($type) {
case 'hasOne':
$values[$this->{$type}[$association]['foreignKey']] = $this->id;
if (!($this->{$association}->create(null) !== null && $this->{$association}->save($values, $options))) {
$validationErrors[$association] = $this->{$association}->validationErrors;
$validates = false;
$validates = $this->{$association}->create(null) !== null;
$saved = false;
if ($validates) {
if ($options['deep']) {
$saved = $this->{$association}->saveAssociated($values, array_merge($options, array('atomic' => false)));
} else {
$saved = $this->{$association}->save($values, $options);
}
}
$return[$association][] = $validates;
$validates = ($validates && ($saved === true || (is_array($saved) && !in_array(false, $saved, true))));
if (!$validates) {
$validationErrors[$association] = $this->{$association}->validationErrors;
}
$return[$association] = $validates;
break;
case 'hasMany':
foreach ($values as $i => $value) {
@ -2217,6 +2269,7 @@ class Model extends Object implements CakeEventListener {
*
* - atomic: If true (default), returns boolean. If false returns array.
* - fieldList: Equivalent to the $fieldList parameter in Model::save()
* - deep: If set to true, not only directly associated data , but deeper nested associated data is validated as well.
*
* @param array $data Record data to validate. This should be an array indexed by association name.
* @param array $options Options to use when validating record data (see above), See also $options of validates().
@ -2225,7 +2278,7 @@ class Model extends Object implements CakeEventListener {
* depending on whether each record validated successfully.
*/
public function validateAssociated($data, $options = array()) {
$options = array_merge(array('atomic' => true), $options);
$options = array_merge(array('atomic' => true, 'deep' => false), $options);
$this->validationErrors = $validationErrors = $return = array();
if (!($this->create($data) && $this->validates($options))) {
$validationErrors[$this->alias] = $this->validationErrors;
@ -2234,12 +2287,23 @@ class Model extends Object implements CakeEventListener {
$return[$this->alias] = true;
}
$associations = $this->getAssociated();
$validates = true;
foreach ($data as $association => $values) {
$validates = true;
if (isset($associations[$association])) {
if (in_array($associations[$association], array('belongsTo', 'hasOne'))) {
$validates = $this->{$association}->create($values) && $this->{$association}->validates($options);
$return[$association][] = $validates;
if ($options['deep']) {
$validates = $this->{$association}->validateAssociated($values, $options);
} else {
$validates = $this->{$association}->create($values) !== null && $this->{$association}->validates($options);
}
if (is_array($validates)) {
if (in_array(false, $validates, true)) {
$validates = false;
} else {
$validates = true;
}
}
$return[$association] = $validates;
} elseif ($associations[$association] === 'hasMany') {
$validates = $this->{$association}->validateMany($values, $options);
$return[$association] = $validates;
@ -2662,6 +2726,10 @@ class Model extends Object implements CakeEventListener {
protected function _findCount($state, $query, $results = array()) {
if ($state === 'before') {
$db = $this->getDataSource();
$query['order'] = false;
if (!method_exists($db, 'calculate') || !method_exists($db, 'expression')) {
return $query;
}
if (empty($query['fields'])) {
$query['fields'] = $db->calculate($this, 'count');
} elseif (is_string($query['fields']) && !preg_match('/count/i', $query['fields'])) {
@ -2669,7 +2737,6 @@ class Model extends Object implements CakeEventListener {
$db->expression($query['fields']), 'count'
));
}
$query['order'] = false;
return $query;
} elseif ($state === 'after') {
foreach (array(0, $this->alias) as $key) {

View file

@ -208,6 +208,7 @@ class CakeResponse {
'hh' => 'text/plain',
'html' => array('text/html', '*/*'),
'htm' => array('text/html', '*/*'),
'ics' => 'text/calendar',
'm' => 'text/plain',
'rtf' => 'text/rtf',
'rtx' => 'text/richtext',
@ -1147,4 +1148,4 @@ class CakeResponse {
$this->_cookies[$config['name']] = $config;
}
}
}

View file

@ -686,6 +686,9 @@ class CakeEmail {
if ($email === $alias) {
$return[] = $email;
} else {
if (strpos($alias, ',') !== false) {
$alias = '"' . $alias . '"';
}
$return[] = sprintf('%s <%s>', $this->_encode($alias), $email);
}
}
@ -1109,9 +1112,6 @@ class CakeEmail {
$restore = mb_internal_encoding();
mb_internal_encoding($this->_appCharset);
}
if (strpos($text, ',') !== false) {
$text = '"' . $text . '"';
}
$return = mb_encode_mimeheader($text, $this->headerCharset, 'B');
if ($internalEncoding) {
mb_internal_encoding($restore);

View file

@ -1077,15 +1077,17 @@ class Router {
* Instructs the router to parse out file extensions from the URL. For example,
* http://example.com/posts.rss would yield an file extension of "rss".
* The file extension itself is made available in the controller as
* $this->params['url']['ext'], and is used by the RequestHandler component to
* `$this->params['ext']`, and is used by the RequestHandler component to
* automatically switch to alternate layouts and templates, and load helpers
* corresponding to the given content, i.e. RssHelper.
* corresponding to the given content, i.e. RssHelper. Switching layouts and helpers
* requires that the chosen extension has a defined mime type in `CakeResponse`
*
* A list of valid extension can be passed to this method, i.e. Router::parseExtensions('rss', 'xml');
* If no parameters are given, anything after the first . (dot) after the last / in the URL will be
* parsed, excluding querystring parameters (i.e. ?q=...).
*
* @return void
* @see RequestHandler::startup()
*/
public static function parseExtensions() {
self::$_parseExtensions = true;

View file

@ -48,13 +48,13 @@ class AllTests extends PHPUnit_Framework_TestSuite {
$suite->addTestFile($path . 'AllEventTest.php');
$suite->addTestFile($path . 'AllHelpersTest.php');
$suite->addTestFile($path . 'AllLogTest.php');
$suite->addTestFile($path . 'AllI18nTest.php');
$suite->addTestFile($path . 'Model' . DS . 'ModelTest.php');
$suite->addTestFile($path . 'AllRoutingTest.php');
$suite->addTestFile($path . 'AllNetworkTest.php');
$suite->addTestFile($path . 'AllTestSuiteTest.php');;
$suite->addTestFile($path . 'AllUtilityTest.php');
$suite->addTestFile($path . 'AllViewTest.php');
$suite->addTestFile($path . 'AllI18nTest.php');
return $suite;
}
}

View file

@ -93,27 +93,37 @@ class ExtractTaskTest extends CakeTestCase {
// home.ctp
$pattern = '/msgid "Your tmp directory is writable."\nmsgstr ""\n/';
$this->assertRegExp($pattern, $result);
$pattern = '/msgid "Your tmp directory is NOT writable."\nmsgstr ""\n/';
$this->assertRegExp($pattern, $result);
$pattern = '/msgid "The %s is being used for caching. To change the config edit ';
$pattern .= 'APP\/config\/core.php "\nmsgstr ""\n/';
$this->assertRegExp($pattern, $result);
$pattern = '/msgid "Your cache is NOT working. Please check ';
$pattern .= 'the settings in APP\/config\/core.php"\nmsgstr ""\n/';
$this->assertRegExp($pattern, $result);
$pattern = '/msgid "Your database configuration file is present."\nmsgstr ""\n/';
$this->assertRegExp($pattern, $result);
$pattern = '/msgid "Your database configuration file is NOT present."\nmsgstr ""\n/';
$this->assertRegExp($pattern, $result);
$pattern = '/msgid "Rename config\/database.php.default to ';
$pattern .= 'config\/database.php"\nmsgstr ""\n/';
$this->assertRegExp($pattern, $result);
$pattern = '/msgid "Cake is able to connect to the database."\nmsgstr ""\n/';
$this->assertRegExp($pattern, $result);
$pattern = '/msgid "Cake is NOT able to connect to the database."\nmsgstr ""\n/';
$this->assertRegExp($pattern, $result);
$pattern = '/msgid "Editing this Page"\nmsgstr ""\n/';
$this->assertRegExp($pattern, $result);
$pattern = '/msgid "To change the content of this page, create: APP\/views\/pages\/home\.ctp/';
$this->assertRegExp($pattern, $result);
@ -121,10 +131,13 @@ class ExtractTaskTest extends CakeTestCase {
$this->assertRegExp($pattern, $result);
// extract.ctp
$pattern = '/\#: (\\\\|\/)extract\.ctp:6\n';
$pattern = '/\#: (\\\\|\/)extract\.ctp:15;6\n';
$pattern .= 'msgid "You have %d new message."\nmsgid_plural "You have %d new messages."/';
$this->assertRegExp($pattern, $result);
$pattern = '/msgid "You have %d new message."\nmsgstr ""/';
$this->assertNotRegExp($pattern, $result, 'No duplicate msgid');
$pattern = '/\#: (\\\\|\/)extract\.ctp:7\n';
$pattern .= 'msgid "You deleted %d message."\nmsgid_plural "You deleted %d messages."/';
$this->assertRegExp($pattern, $result);
@ -134,7 +147,7 @@ class ExtractTaskTest extends CakeTestCase {
$pattern .= 'msgid "Editing this Page"\nmsgstr ""/';
$this->assertRegExp($pattern, $result);
$pattern = '/\#: (\\\\|\/)extract\.ctp:17\nmsgid "';
$pattern = '/\#: (\\\\|\/)extract\.ctp:18\nmsgid "';
$pattern .= 'Hot features!';
$pattern .= '\\\n - No Configuration: Set-up the database and let the magic begin';
$pattern .= '\\\n - Extremely Simple: Just look at the name...It\'s Cake';

View file

@ -75,7 +75,7 @@ class ActionsAuthorizeTest extends CakeTestCase {
$this->Acl->expects($this->once())
->method('check')
->with($user, '/controllers/Posts/index')
->with($user, 'controllers/Posts/index')
->will($this->returnValue(false));
$this->assertFalse($this->auth->authorize($user['User'], $request));
@ -104,7 +104,7 @@ class ActionsAuthorizeTest extends CakeTestCase {
$this->Acl->expects($this->once())
->method('check')
->with($user, '/controllers/Posts/index')
->with($user, 'controllers/Posts/index')
->will($this->returnValue(true));
$this->assertTrue($this->auth->authorize($user['User'], $request));
@ -134,7 +134,7 @@ class ActionsAuthorizeTest extends CakeTestCase {
$expected = array('TestPlugin.TestPluginAuthUser' => array('id' => 1, 'user' => 'mariano'));
$this->Acl->expects($this->once())
->method('check')
->with($expected, '/controllers/Posts/index')
->with($expected, 'controllers/Posts/index')
->will($this->returnValue(true));
$this->assertTrue($this->auth->authorize($user, $request));
@ -154,8 +154,23 @@ class ActionsAuthorizeTest extends CakeTestCase {
));
$result = $this->auth->action($request);
$this->assertEquals('controllers/Posts/index', $result);
}
$this->assertEquals('/controllers/Posts/index', $result);
/**
* Make sure that action() doesn't create double slashes anywhere.
*
* @return void
*/
public function testActionNoDoubleSlash() {
$this->auth->settings['actionPath'] = '/controllers/';
$request = array(
'plugin' => null,
'controller' => 'posts',
'action' => 'index'
);
$result = $this->auth->action($request);
$this->assertEquals('controllers/Posts/index', $result);
}
/**
@ -172,6 +187,6 @@ class ActionsAuthorizeTest extends CakeTestCase {
));
$result = $this->auth->action($request);
$this->assertEquals('/controllers/DebugKit/Posts/index', $result);
$this->assertEquals('controllers/DebugKit/Posts/index', $result);
}
}

View file

@ -490,6 +490,21 @@ class CookieComponentTest extends CakeTestCase {
$this->assertEquals($expected, $result);
}
/**
* Test reading empty values.
*/
public function testReadEmpty() {
$_COOKIE['CakeTestCookie'] = array(
'JSON' => '{"name":"value"}',
'Empty' => '',
'String' => '{"somewhat:"broken"}'
);
$this->assertEqual(array('name' => 'value'), $this->Cookie->read('JSON'));
$this->assertEqual('value', $this->Cookie->read('JSON.name'));
$this->assertEqual('', $this->Cookie->read('Empty'));
$this->assertEqual('{"somewhat:"broken"}', $this->Cookie->read('String'));
}
/**
* test that no error is issued for non array data.
*
@ -502,6 +517,7 @@ class CookieComponentTest extends CakeTestCase {
$this->assertNull($this->Cookie->read('value'));
}
/**
* test that deleting a top level keys kills the child elements too.
*

View file

@ -915,7 +915,7 @@ class SecurityComponentTest extends CakeTestCase {
* @return void
*/
public function testValidateNestedNumericSets() {
$this->Controller->Security->startup($this->Controller);
$key = $this->Controller->request->params['_Token']['key'];
$unlocked = '';
@ -1122,13 +1122,15 @@ class SecurityComponentTest extends CakeTestCase {
$this->Security->validatePost = false;
$this->Security->csrfCheck = true;
$this->Security->csrfExpires = '+10 minutes';
$csrfExpires = strtotime('+10 minutes');
$this->Security->startup($this->Controller);
$this->Security->startup($this->Controller);
$token = $this->Security->Session->read('_Token');
$this->assertEquals(count($token['csrfTokens']), 2, 'Missing the csrf token.');
foreach ($token['csrfTokens'] as $key => $expires) {
$this->assertEquals(strtotime('+10 minutes'), $expires, 'Token expiry does not match');
$diff = $csrfExpires - $expires;
$this->assertTrue($diff === 0 || $diff === 1, 'Token expiry does not match');
}
}

View file

@ -2525,6 +2525,7 @@ class I18nTest extends CakeTestCase {
* @return void
*/
public function testPoQuotedString () {
Configure::write('Config.language', 'po');
$expected = 'this is a "quoted string" (translated)';
$this->assertEquals($expected, __('this is a "quoted string"'));
}

View file

@ -278,13 +278,13 @@ class SqliteTest extends CakeTestCase {
'user' => array(
'type' => 'string',
'length' => 255,
'null' => false,
'null' => true,
'default' => null
),
'password' => array(
'type' => 'string',
'length' => 255,
'null' => false,
'null' => true,
'default' => null
),
'created' => array(

View file

@ -633,4 +633,31 @@ class SqlserverTest extends CakeTestCase {
$this->assertEquals('nate', $results[1]['User']['user']);
}
/**
* Test that the return of stored procedures is honoured
*
* @return void
*/
public function testStoredProcedureReturn() {
$sql = <<<SQL
CREATE PROCEDURE cake_test_procedure
AS
BEGIN
RETURN 2;
END
SQL;
$this->Dbo->execute($sql);
$sql = <<<SQL
DECLARE @return_value int
EXEC @return_value = [cake_test_procedure]
SELECT 'value' = @return_value
SQL;
$query = $this->Dbo->execute($sql);
$this->Dbo->execute('DROP PROC cake_test_procedure');
$result = $query->fetch();
$this->assertEquals(2, $result['value']);
}
}

View file

@ -46,7 +46,7 @@ class CacheSessionTest extends CakeTestCase {
* @return void
*/
public static function teardownAfterClass() {
Cache::clear('session_test');
Cache::clear(false, 'session_test');
Cache::drop('session_test');
Configure::write('Session', self::$_sessionBackup);

View file

@ -555,7 +555,9 @@ class ModelDeleteTest extends BaseModelTest {
* @return void
*/
public function testDeleteDependent() {
$this->loadFixtures('Bidding', 'BiddingMessage');
$this->loadFixtures('Bidding', 'BiddingMessage', 'Article',
'ArticlesTag', 'Comment', 'User', 'Attachment'
);
$Bidding = new Bidding();
$result = $Bidding->find('all');
$expected = array(
@ -626,6 +628,20 @@ class ModelDeleteTest extends BaseModelTest {
),
);
$this->assertEquals($expected, $result);
$Article = new Article();
$result = $Article->Comment->find('count', array(
'conditions' => array('Comment.article_id' => 1)
));
$this->assertEquals(4, $result);
$result = $Article->delete(1, true);
$this->assertIdentical(true, true);
$result = $Article->Comment->find('count', array(
'conditions' => array('Comment.article_id' => 1)
));
$this->assertEquals(0, $result);
}
/**

View file

@ -2083,13 +2083,13 @@ class ModelIntegrationTest extends BaseModelTest {
),
'user' => array(
'type' => 'string',
'null' => false,
'null' => true,
'default' => '',
'length' => 255
),
'password' => array(
'type' => 'string',
'null' => false,
'null' => true,
'default' => '',
'length' => 255
),

View file

@ -2973,7 +2973,7 @@ class ModelWriteTest extends BaseModelTest {
* @return void
*/
public function testSaveAllAtomic() {
$this->loadFixtures('Article', 'User');
$this->loadFixtures('Article', 'User', 'Comment');
$TestModel = new Article();
$result = $TestModel->saveAll(array(
@ -3041,6 +3041,779 @@ class ModelWriteTest extends BaseModelTest {
$this->assertSame($result, array('Article' => true, 'Comment' => array(true, true)));
}
/**
* testSaveAllDeepAssociated method
*
* @return void
*/
public function testSaveAllDeepAssociated() {
$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
$TestModel = new Article();
$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
$TestModel->hasAndBelongsToMany = array();
$result = $TestModel->saveAll(array(
'Article' => array('id' => 2),
'Comment' => array(
array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => 'newuser', 'password' => 'newuserpass')),
array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
)
), array('deep' => true));
$this->assertTrue($result);
$result = $TestModel->findById(2);
$expected = array(
'First Comment for Second Article',
'Second Comment for Second Article',
'First new comment',
'Second new comment'
);
$this->assertEquals($expected, Set::extract($result['Comment'], '{n}.comment'));
$result = $TestModel->Comment->User->field('id', array('user' => 'newuser', 'password' => 'newuserpass'));
$this->assertEquals(5, $result);
$result = $TestModel->saveAll(array(
'Article' => array('id' => 2),
'Comment' => array(
array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => 'deepsaved'))
)
), array('deep' => true));
$this->assertTrue($result);
$result = $TestModel->findById(2);
$expected = array(
'First Comment for Second Article',
'Second Comment for Second Article',
'First new comment',
'Second new comment',
'Third new comment',
'Fourth new comment'
);
$this->assertEquals($expected, Set::extract($result['Comment'], '{n}.comment'));
$result = $TestModel->Comment->Attachment->field('id', array('attachment' => 'deepsaved'));
$this->assertEquals(2, $result);
$data = array(
'Attachment' => array(
'attachment' => 'deepsave insert',
),
'Comment' => array(
'comment' => 'First comment deepsave insert',
'published' => 'Y',
'user_id' => 5,
'Article' => array(
'title' => 'First Article deepsave insert',
'body' => 'First Article Body deepsave insert',
'User' => array(
'user' => '',
'password' => 'magic'
),
),
)
);
$TestModel->Comment->Attachment->create();
$result = $TestModel->Comment->Attachment->saveAll($data, array('deep' => true));
$this->assertFalse($result);
$expected = array('User' => array('user' => array('This field cannot be left blank')));
$this->assertEquals($expected, $TestModel->validationErrors);
$data['Comment']['Article']['User']['user'] = 'deepsave';
$TestModel->Comment->Attachment->create();
$result = $TestModel->Comment->Attachment->saveAll($data, array('deep' => true));
$this->assertTrue($result);
$result = $TestModel->Comment->Attachment->findById($TestModel->Comment->Attachment->id);
$expected = array(
'Attachment' => array(
'id' => '3',
'comment_id' => '11',
'attachment' => 'deepsave insert',
),
'Comment' => array(
'id' => '11',
'article_id' => '4',
'user_id' => '5',
'comment' => 'First comment deepsave insert',
'published' => 'Y',
)
);
unset($result['Attachment']['created'], $result['Attachment']['updated']);
$this->assertEquals($expected['Attachment'], $result['Attachment']);
unset($result['Comment']['created'], $result['Comment']['updated']);
$this->assertEquals($result['Comment'], $expected['Comment']);
$result = $TestModel->findById($result['Comment']['article_id']);
$expected = array(
'Article' => array(
'id' => '4',
'user_id' => '6',
'title' => 'First Article deepsave insert',
'body' => 'First Article Body deepsave insert',
'published' => 'N',
),
'User' => array(
'id' => '6',
'user' => 'deepsave',
'password' => 'magic',
),
'Comment' => array(
array(
'id' => '11',
'article_id' => '4',
'user_id' => '5',
'comment' => 'First comment deepsave insert',
'published' => 'Y',
)
)
);
unset(
$result['Article']['created'], $result['Article']['updated'],
$result['User']['created'], $result['User']['updated'],
$result['Comment'][0]['created'], $result['Comment'][0]['updated']
);
$this->assertEquals($result, $expected);
}
/**
* testSaveAllDeepMany
* tests the validate methods with deeper recursive data
*
* @return void
*/
public function testSaveAllDeepMany() {
$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
$TestModel = new Article();
$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
$TestModel->hasAndBelongsToMany = array();
$data = array(
array(
'id' => 1, 'body' => '',
'Comment' => array(
array('comment' => '', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'manysaved')),
array('comment' => 'Second comment deepsaved article 1', 'published' => 'Y', 'user_id' => 2)
)
),
array(
'Article' => array('id' => 2),
'Comment' => array(
array('comment' => 'First comment deepsaved article 2', 'published' => 'Y', 'User' => array('user' => 'savemore', 'password' => '')),
array('comment' => '', 'published' => 'Y', 'user_id' => 2)
)
)
);
$TestModel->Comment->validate['comment'] = 'notEmpty';
$result = $TestModel->saveAll($data, array('deep' => true));
$this->assertFalse($result);
$expected = array(
0 => array(
'body' => array('This field cannot be left blank')
),
1 => array(
'Comment' => array(
0 => array(
'User' => array(
'password' => array('This field cannot be left blank')
)
),
1 => array(
'comment' => array('This field cannot be left blank')
)
)
)
);
$result = $TestModel->validationErrors;
$this->assertSame($expected, $result);
$data = array(
array(
'Article' => array('id' => 1),
'Comment' => array(
array('comment' => 'First comment deepsaved article 1', 'published' => 'Y', 'User' => array('user' => 'savemany', 'password' => 'manysaved')),
array('comment' => 'Second comment deepsaved article 1', 'published' => 'Y', 'user_id' => 2)
)
),
array(
'Article' => array('id' => 2),
'Comment' => array(
array('comment' => 'First comment deepsaved article 2', 'published' => 'Y', 'User' => array('user' => 'savemore', 'password' => 'moresaved')),
array('comment' => 'Second comment deepsaved article 2', 'published' => 'Y', 'user_id' => 2)
)
)
);
$result = $TestModel->saveAll($data, array('deep' => true));
$this->assertTrue($result);
}
/**
* testSaveAllDeepValidateOnly
* tests the validate methods with deeper recursive data
*
* @return void
*/
public function testSaveAllDeepValidateOnly() {
$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
$TestModel = new Article();
$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
$TestModel->hasAndBelongsToMany = array();
$TestModel->Comment->Attachment->validate['attachment'] = 'notEmpty';
$TestModel->Comment->validate['comment'] = 'notEmpty';
$result = $TestModel->saveAll(
array(
'Article' => array('id' => 2),
'Comment' => array(
array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => 'newuser', 'password' => 'newuserpass')),
array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
)
),
array('validate' => 'only', 'deep' => true)
);
$this->assertTrue($result);
$result = $TestModel->saveAll(
array(
'Article' => array('id' => 2),
'Comment' => array(
array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
)
),
array('validate' => 'only', 'deep' => true)
);
$this->assertFalse($result);
$result = $TestModel->saveAll(
array(
'Article' => array('id' => 2),
'Comment' => array(
array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => 'newuser', 'password' => 'newuserpass')),
array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
)
),
array('validate' => 'only', 'atomic' => false, 'deep' => true)
);
$expected = array(
'Article' => true,
'Comment' => array(
true,
true
)
);
$this->assertSame($expected, $result);
$result = $TestModel->saveAll(
array(
'Article' => array('id' => 2),
'Comment' => array(
array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
)
),
array('validate' => 'only', 'atomic' => false, 'deep' => true)
);
$expected = array(
'Article' => true,
'Comment' => array(
false,
true
)
);
$this->assertSame($expected, $result);
$result = $TestModel->saveAll(array(
'Article' => array('id' => 2),
'Comment' => array(
array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => 'deepsaved'))
)
),
array('validate' => 'only', 'deep' => true)
);
$this->assertTrue($result);
$result = $TestModel->saveAll(array(
'Article' => array('id' => 2),
'Comment' => array(
array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
)
),
array('validate' => 'only', 'deep' => true)
);
$this->assertFalse($result);
$result = $TestModel->saveAll(array(
'Article' => array('id' => 2),
'Comment' => array(
array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => 'deepsave'))
)
),
array('validate' => 'only', 'atomic' => false, 'deep' => true)
);
$expected = array(
'Article' => true,
'Comment' => array(
true,
true
)
);
$this->assertSame($expected, $result);
$result = $TestModel->saveAll(array(
'Article' => array('id' => 2),
'Comment' => array(
array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
)
),
array('validate' => 'only', 'atomic' => false, 'deep' => true)
);
$expected = array(
'Article' => true,
'Comment' => array(
true,
false
)
);
$this->assertSame($expected, $result);
$expected = array(
'Comment' => array(
1 => array(
'Attachment' => array(
'attachment' => array('This field cannot be left blank')
)
)
)
);
$result = $TestModel->validationErrors;
$this->assertSame($expected, $result);
$data = array(
'Attachment' => array(
'attachment' => 'deepsave insert',
),
'Comment' => array(
'comment' => 'First comment deepsave insert',
'published' => 'Y',
'user_id' => 5,
'Article' => array(
'title' => 'First Article deepsave insert',
'body' => 'First Article Body deepsave insert',
'User' => array(
'user' => 'deepsave',
'password' => 'magic'
),
),
)
);
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
$this->assertTrue($result);
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
$expected = array(
'Attachment' => true,
'Comment' => true
);
$this->assertSame($expected, $result);
$data = array(
'Attachment' => array(
'attachment' => 'deepsave insert',
),
'Comment' => array(
'comment' => 'First comment deepsave insert',
'published' => 'Y',
'user_id' => 5,
'Article' => array(
'title' => 'First Article deepsave insert',
'body' => 'First Article Body deepsave insert',
'User' => array(
'user' => '',
'password' => 'magic'
),
),
)
);
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
$this->assertFalse($result);
$result = $TestModel->Comment->Attachment->validationErrors;
$expected = array(
'Comment' => array(
'Article' => array(
'User' => array(
'user' => array('This field cannot be left blank')
)
)
)
);
$this->assertSame($expected, $result);
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
$expected = array(
'Attachment' => true,
'Comment' => false
);
$this->assertEquals($expected, $result);
$data['Comment']['Article']['body'] = '';
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
$this->assertFalse($result);
$result = $TestModel->Comment->Attachment->validationErrors;
$expected = array(
'Comment' => array(
'Article' => array(
'body' => array('This field cannot be left blank')
)
)
);
$this->assertSame($expected, $result);
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
$expected = array(
'Attachment' => true,
'Comment' => false
);
$this->assertEquals($expected, $result);
$data['Comment']['comment'] = '';
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
$this->assertFalse($result);
$result = $TestModel->Comment->Attachment->validationErrors;
$expected = array(
'Comment' => array(
'comment' => array('This field cannot be left blank')
)
);
$this->assertSame($expected, $result);
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
$expected = array(
'Attachment' => true,
'Comment' => false
);
$this->assertEquals($expected, $result);
$data['Attachment']['attachment'] = '';
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => true));
$this->assertFalse($result);
$result = $TestModel->Comment->Attachment->validationErrors;
$expected = array('attachment' => array('This field cannot be left blank'));
$this->assertSame($expected, $result);
$result = $TestModel->Comment->validationErrors;
$expected = array('comment' => array('This field cannot be left blank'));
$this->assertSame($expected, $result);
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true));
$expected = array(
'Attachment' => false,
'Comment' => false
);
$this->assertEquals($expected, $result);
}
/**
* testSaveAllNotDeepAssociated method
* test that only directly associated data gets saved
*
* @return void
*/
public function testSaveAllNotDeepAssociated() {
$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
$TestModel = new Article();
$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
$TestModel->hasAndBelongsToMany = array();
$result = $TestModel->saveAll(array(
'Article' => array('id' => 2),
'Comment' => array(
array(
'comment' => 'First new comment', 'published' => 'Y', 'user_id' => 2,
'User' => array('user' => 'newuser', 'password' => 'newuserpass')
),
array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
)
), array('deep' => false));
$this->assertTrue($result);
$result = $TestModel->Comment->User->field('id', array('user' => 'newuser', 'password' => 'newuserpass'));
$this->assertFalse($result);
$result = $TestModel->saveAll(array(
'Article' => array('id' => 2),
'Comment' => array(
array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 4),
array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => 'deepsaved'))
)
), array('deep' => false));
$this->assertTrue($result);
$result = $TestModel->Comment->Attachment->field('id', array('attachment' => 'deepsaved'));
$this->assertFalse($result);
$data = array(
'Attachment' => array(
'attachment' => 'deepsave insert',
),
'Comment' => array(
'comment' => 'First comment deepsave insert',
'published' => 'Y',
'user_id' => 4,
'article_id' => 1,
'Article' => array(
'title' => 'First Article deepsave insert',
'body' => 'First Article Body deepsave insert',
'User' => array(
'user' => 'deepsave',
'password' => 'magic'
),
),
)
);
$expected = $TestModel->User->find('count');
$TestModel->Comment->Attachment->create();
$result = $TestModel->Comment->Attachment->saveAll($data, array('deep' => false));
$this->assertTrue($result);
$result = $TestModel->User->find('count');
$this->assertEquals($expected, $result);
$result = $TestModel->Comment->Attachment->findById($TestModel->Comment->Attachment->id);
$expected = array(
'Attachment' => array(
'id' => '2',
'comment_id' => '11',
'attachment' => 'deepsave insert',
),
'Comment' => array(
'id' => '11',
'article_id' => 1,
'user_id' => '4',
'comment' => 'First comment deepsave insert',
'published' => 'Y',
)
);
unset($result['Attachment']['created'], $result['Attachment']['updated']);
$this->assertEquals($expected['Attachment'], $result['Attachment']);
unset($result['Comment']['created'], $result['Comment']['updated']);
$this->assertEquals($expected['Comment'], $result['Comment']);
}
/**
* testSaveAllNotDeepMany
* tests the save methods to not save deeper recursive data
*
* @return void
*/
public function testSaveAllNotDeepMany() {
$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
$TestModel = new Article();
$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
$TestModel->hasAndBelongsToMany = array();
$data = array(
array(
'id' => 1, 'body' => '',
'Comment' => array(
array('comment' => '', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'manysaved')),
array('comment' => 'Second comment deepsaved article 1', 'published' => 'Y', 'user_id' => 2)
)
),
array(
'Article' => array('id' => 2),
'Comment' => array(
array('comment' => 'First comment deepsaved article 2', 'published' => 'Y', 'User' => array('user' => 'savemore', 'password' => '')),
array('comment' => '', 'published' => 'Y', 'user_id' => 2)
)
)
);
$TestModel->Comment->validate['comment'] = 'notEmpty';
$result = $TestModel->saveAll($data, array('deep' => false));
$this->assertFalse($result);
$expected = array(
0 => array(
'body' => array('This field cannot be left blank')
)
);
$result = $TestModel->validationErrors;
$this->assertSame($expected, $result);
$data = array(
array(
'Article' => array('id' => 1, 'body' => 'Ignore invalid comment'),
'Comment' => array(
array('comment' => '', 'published' => 'Y', 'user_id' => 2)
)
),
array(
'Article' => array('id' => 2, 'body' => 'Same here'),
'Comment' => array(
array('comment' => '', 'published' => 'Y', 'user_id' => 2)
)
)
);
$result = $TestModel->saveAll($data, array('deep' => false));
$this->assertTrue($result);
}
/**
* testSaveAllNotDeepValidateOnly
* tests the validate methods to not validate deeper recursive data
*
* @return void
*/
public function testSaveAllNotDeepValidateOnly() {
$this->loadFixtures('Article', 'Comment', 'User', 'Attachment');
$TestModel = new Article();
$TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC');
$TestModel->hasAndBelongsToMany = array();
$TestModel->Comment->Attachment->validate['attachment'] = 'notEmpty';
$TestModel->Comment->validate['comment'] = 'notEmpty';
$result = $TestModel->saveAll(
array(
'Article' => array('id' => 2, 'body' => ''),
'Comment' => array(
array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
)
),
array('validate' => 'only', 'deep' => false)
);
$this->assertFalse($result);
$expected = array('body' => array('This field cannot be left blank'));
$result = $TestModel->validationErrors;
$this->assertSame($expected, $result);
$result = $TestModel->saveAll(
array(
'Article' => array('id' => 2, 'body' => 'Ignore invalid user data'),
'Comment' => array(
array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
)
),
array('validate' => 'only', 'deep' => false)
);
$this->assertTrue($result);
$result = $TestModel->saveAll(
array(
'Article' => array('id' => 2, 'body' => 'Ignore invalid user data'),
'Comment' => array(
array('comment' => 'First new comment', 'published' => 'Y', 'User' => array('user' => '', 'password' => 'newuserpass')),
array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
)
),
array('validate' => 'only', 'atomic' => false, 'deep' => false)
);
$expected = array(
'Article' => true,
'Comment' => array(
true,
true
)
);
$this->assertSame($expected, $result);
$result = $TestModel->saveAll(array(
'Article' => array('id' => 2, 'body' => 'Ignore invalid attachment data'),
'Comment' => array(
array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
)
),
array('validate' => 'only', 'deep' => false)
);
$this->assertTrue($result);
$result = $TestModel->saveAll(array(
'Article' => array('id' => 2, 'body' => 'Ignore invalid attachment data'),
'Comment' => array(
array('comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 5),
array('comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 2, 'Attachment' => array('attachment' => ''))
)
),
array('validate' => 'only', 'atomic' => false, 'deep' => false)
);
$expected = array(
'Article' => true,
'Comment' => array(
true,
true
)
);
$this->assertSame($expected, $result);
$expected = array();
$result = $TestModel->validationErrors;
$this->assertSame($expected, $result);
$data = array(
'Attachment' => array(
'attachment' => 'deepsave insert',
),
'Comment' => array(
'comment' => 'First comment deepsave insert',
'published' => 'Y',
'user_id' => 5,
'Article' => array(
'title' => 'First Article deepsave insert ignored',
'body' => 'First Article Body deepsave insert',
'User' => array(
'user' => '',
'password' => 'magic'
),
),
)
);
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => false));
$this->assertTrue($result);
$result = $TestModel->Comment->Attachment->validationErrors;
$expected = array();
$this->assertSame($expected, $result);
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false));
$expected = array(
'Attachment' => true,
'Comment' => true
);
$this->assertEquals($expected, $result);
$data['Comment']['Article']['body'] = '';
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'deep' => false));
$this->assertTrue($result);
$result = $TestModel->Comment->Attachment->validationErrors;
$expected = array();
$this->assertSame($expected, $result);
$result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false));
$expected = array(
'Attachment' => true,
'Comment' => true
);
$this->assertEquals($expected, $result);
}
/**
* testSaveAllHasMany method
*
@ -3212,7 +3985,7 @@ class ModelWriteTest extends BaseModelTest {
$db->expects($this->once())->method('rollback');
$db->expects($this->any())->method('describe')
->will($this->returnValue(array(
'id' => array('type' => 'integer'),
'id' => array('type' => 'integer', 'length' => 11),
'title' => array('type' => 'string'),
'body' => array('type' => 'text'),
'published' => array('type' => 'string')
@ -3409,7 +4182,8 @@ class ModelWriteTest extends BaseModelTest {
$result = $TestModel->find('all', array(
'recursive' => -1,
'fields' => array('author_id', 'title','body','published')
'fields' => array('author_id', 'title','body','published'),
'order' => array('Post.created' => 'ASC')
));
$expected = array(
@ -4540,7 +5314,7 @@ class ModelWriteTest extends BaseModelTest {
$db->expects($this->once())->method('rollback');
$db->expects($this->any())->method('describe')
->will($this->returnValue(array(
'id' => array('type' => 'integer'),
'id' => array('type' => 'integer', 'length' => 11),
'title' => array('type' => 'string'),
'body' => array('type' => 'text'),
'published' => array('type' => 'string')
@ -4741,7 +5515,8 @@ class ModelWriteTest extends BaseModelTest {
$result = $TestModel->find('all', array(
'recursive' => -1,
'fields' => array('author_id', 'title','body','published')
'fields' => array('author_id', 'title','body','published'),
'order' => array('Post.created' => 'ASC')
));
$expected = array(
@ -5510,11 +6285,11 @@ class ModelWriteTest extends BaseModelTest {
}
/**
* validateSaveAllFieldListBelongsTo
* testSaveAllFieldListValidateBelongsTo
*
* @return void
*/
public function validateSaveAllFieldListBelongsTo() {
public function testSaveAllFieldListValidateBelongsTo() {
$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment');
$TestModel = new Post();
@ -5541,8 +6316,7 @@ class ModelWriteTest extends BaseModelTest {
$result = $TestModel->find('all');
$expected = array(
'Post' =>
array (
'Post' => array (
'id' => '4',
'author_id' => '5',
'title' => 'Post without body',
@ -5551,8 +6325,7 @@ class ModelWriteTest extends BaseModelTest {
'created' => $ts,
'updated' => $ts,
),
'Author' =>
array (
'Author' => array (
'id' => '5',
'user' => 'bob',
'password' => NULL,
@ -5681,4 +6454,95 @@ class ModelWriteTest extends BaseModelTest {
$this->assertEmpty($TestModel->validationErrors);
}
/**
* testSaveAllDeepFieldListValidateBelongsTo
*
* @return void
*/
public function testSaveAllDeepFieldListValidateBelongsTo() {
$this->loadFixtures('Post', 'Author', 'Comment', 'Attachment', 'Article', 'User');
$TestModel = new Post();
$TestModel->Author->bindModel(array('hasMany' => array('Comment' => array('foreignKey' => 'user_id'))), false);
$TestModel->recursive = 2;
$result = $TestModel->find('all');
$this->assertCount(3, $result);
$this->assertFalse(isset($result[3]));
$ts = date('Y-m-d H:i:s');
// test belongsTo
$fieldList = array(
'Post' => array('title', 'author_id'),
'Author' => array('user'),
'Comment' => array('comment')
);
$TestModel->saveAll(array(
'Post' => array(
'title' => 'Post without body',
'body' => 'This will not be saved',
),
'Author' => array(
'user' => 'bob',
'test' => 'This will not be saved',
'Comment' => array(
array('id' => 5, 'comment' => 'I am still published', 'published' => 'N'))
)), array('fieldList' => $fieldList, 'deep' => true));
$result = $TestModel->Author->Comment->find('first', array(
'conditions' => array('Comment.id' => 5),
'fields' => array('comment', 'published')
));
$expected = array(
'Comment' => array(
'comment' => 'I am still published',
'published' => 'Y'
)
);
$this->assertEquals($expected, $result);
}
/**
* testSaveAllDeepFieldListHasMany method
*
* return @void
*/
public function testSaveAllDeepFieldListHasMany() {
$this->loadFixtures('Article', 'Comment', 'User');
$TestModel = new Article();
$TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array();
$this->db->truncate($TestModel);
$this->db->truncate(new Comment());
$fieldList = array(
'Article' => array('id'),
'Comment' => array('article_id', 'user_id'),
'User' => array('user')
);
$result = $TestModel->saveAll(array(
'Article' => array('id' => 2, 'title' => 'I will not save'),
'Comment' => array(
array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
array(
'comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2,
'User' => array('user' => 'nopassword', 'password' => 'not saved')
)
)
), array('fieldList' => $fieldList, 'deep' => true));
$result = $TestModel->Comment->User->find('first', array(
'conditions' => array('User.user' => 'nopassword'),
'fields' => array('user', 'password')
));
$expected = array(
'User' => array(
'user' => 'nopassword',
'password' => ''
)
);
$this->assertEquals($expected, $result);
}
}

View file

@ -641,6 +641,13 @@ class Attachment extends CakeTestModel {
* @var string 'Attachment'
*/
public $name = 'Attachment';
/**
* belongsTo property
*
* @var array
*/
public $belongsTo = array('Comment');
}
/**

View file

@ -395,6 +395,8 @@ class CakeEmailTest extends CakeTestCase {
$this->CakeEmail->subject('You have a new message.');
$this->assertSame($this->CakeEmail->subject(), 'You have a new message.');
$this->CakeEmail->subject('You have a new message, I think.');
$this->assertSame($this->CakeEmail->subject(), 'You have a new message, I think.');
$this->CakeEmail->subject(1);
$this->assertSame($this->CakeEmail->subject(), '1');

View file

@ -49,13 +49,15 @@ class DebugTransportTest extends CakeTestCase {
$email->bcc('phpnut@cakephp.org');
$email->messageID('<4d9946cf-0a44-4907-88fe-1d0ccbdd56cb@localhost>');
$email->subject('Testing Message');
$date = date(DATE_RFC2822);
$email->setHeaders(array('X-Mailer' => $email::EMAIL_CLIENT, 'Date' => $date));
$email->expects($this->any())->method('message')->will($this->returnValue(array('First Line', 'Second Line', '')));
$headers = "From: CakePHP Test <noreply@cakephp.org>\r\n";
$headers .= "To: CakePHP <cake@cakephp.org>\r\n";
$headers .= "Cc: Mark Story <mark@cakephp.org>, Juan Basso <juan@cakephp.org>\r\n";
$headers .= "X-Mailer: CakePHP Email\r\n";
$headers .= "Date: " . date(DATE_RFC2822) . "\r\n";
$headers .= "Date: " . $date . "\r\n";
$headers .= "Message-ID: <4d9946cf-0a44-4907-88fe-1d0ccbdd56cb@localhost>\r\n";
$headers .= "Subject: Testing Message\r\n";
$headers .= "MIME-Version: 1.0\r\n";

View file

@ -220,6 +220,8 @@ class SmtpTransportTest extends CakeTestCase {
$email->bcc('phpnut@cakephp.org');
$email->messageID('<4d9946cf-0a44-4907-88fe-1d0ccbdd56cb@localhost>');
$email->subject('Testing SMTP');
$date = date(DATE_RFC2822);
$email->setHeaders(array('X-Mailer' => $email::EMAIL_CLIENT, 'Date' => $date));
$email->expects($this->any())->method('message')->will($this->returnValue(array('First Line', 'Second Line', '')));
$data = "From: CakePHP Test <noreply@cakephp.org>\r\n";
@ -227,7 +229,7 @@ class SmtpTransportTest extends CakeTestCase {
$data .= "To: CakePHP <cake@cakephp.org>\r\n";
$data .= "Cc: Mark Story <mark@cakephp.org>, Juan Basso <juan@cakephp.org>\r\n";
$data .= "X-Mailer: CakePHP Email\r\n";
$data .= "Date: " . date(DATE_RFC2822) . "\r\n";
$data .= "Date: " . $date . "\r\n";
$data .= "Message-ID: <4d9946cf-0a44-4907-88fe-1d0ccbdd56cb@localhost>\r\n";
$data .= "Subject: Testing SMTP\r\n";
$data .= "MIME-Version: 1.0\r\n";

View file

@ -0,0 +1,462 @@
<?php
/**
* CakeNumberTest file
*
* PHP 5
*
* CakePHP(tm) Tests <http://book.cakephp.org/view/1196/Testing>
* 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.Test.Case.View.Helper
* @since CakePHP(tm) v 1.2.0.4206
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::uses('View', 'View');
App::uses('CakeNumber', 'Utility');
/**
* CakeNumberTest class
*
* @package Cake.Test.Case.Utility
*/
class CakeNumberTest extends CakeTestCase {
/**
* setUp method
*
* @return void
*/
public function setUp() {
parent::setUp();
$this->Number = new CakeNumber();
}
/**
* tearDown method
*
* @return void
*/
public function tearDown() {
parent::tearDown();
unset($this->Number);
}
/**
* testFormatAndCurrency method
*
* @return void
*/
public function testFormat() {
$value = '100100100';
$result = $this->Number->format($value, '#');
$expected = '#100,100,100';
$this->assertEquals($expected, $result);
$result = $this->Number->format($value, 3);
$expected = '100,100,100.000';
$this->assertEquals($expected, $result);
$result = $this->Number->format($value);
$expected = '100,100,100';
$this->assertEquals($expected, $result);
$result = $this->Number->format($value, '-');
$expected = '100-100-100';
$this->assertEquals($expected, $result);
}
/**
* Test currency method.
*
* @return void
*/
public function testCurrency() {
$value = '100100100';
$result = $this->Number->currency($value);
$expected = '$100,100,100.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, '#');
$expected = '#100,100,100.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, false);
$expected = '100,100,100.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'USD');
$expected = '$100,100,100.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'EUR');
$expected = '&#8364;100.100.100,00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'GBP');
$expected = '&#163;100,100,100.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, '', array('thousands' => ' ', 'wholeSymbol' => '€', 'wholePosition' => 'after', 'decimals' => ',', 'zero' => 'Gratuit'));
$expected = '100 100 100,00€';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(1000.45, NULL, array('after' => 'øre', 'before' => 'Kr. ', 'decimals' => ',', 'thousands' => '.'));
$expected = 'Kr. 1.000,45';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(0.5, 'USD');
$expected = '50c';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(0.5, NULL, array('after' => 'øre'));
$expected = '50øre';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(1, null, array('wholeSymbol' => '$ '));
$expected = '$ 1.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(1, null, array('wholeSymbol' => ' $', 'wholePosition' => 'after'));
$expected = '1.00 $';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(0.2, null, array('wholeSymbol' => ' $', 'wholePosition' => 'after', 'fractionSymbol' => 'cents'));
$expected = '20cents';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(0.2, null, array('wholeSymbol' => ' $', 'wholePosition' => 'after', 'fractionSymbol' => 'cents', 'fractionPosition' => 'before'));
$expected = 'cents20';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(311, 'USD', array('wholePosition' => 'after'));
$expected = '311.00$';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(0.2, 'EUR');
$expected = '&#8364;0,20';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(12, null, array('wholeSymbol' => ' dollars', 'wholePosition' => 'after', 'fractionSymbol' => ' cents', 'fractionPosition' => 'after'));
$expected = '12.00 dollars';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(0.12, null, array('wholeSymbol' => ' dollars', 'wholePosition' => 'after', 'fractionSymbol' => ' cents', 'fractionPosition' => 'after'));
$expected = '12 cents';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(0.5, null, array('fractionSymbol' => false, 'fractionPosition' => 'before', 'wholeSymbol' => '$'));
$expected = '$0.50';
$this->assertEquals($expected, $result);
}
/**
* Test adding currency format options to the number helper
*
* @return void
*/
public function testCurrencyAddFormat() {
$this->Number->addFormat('NOK', array('before' => 'Kr. '));
$result = $this->Number->currency(1000, 'NOK');
$expected = 'Kr. 1,000.00';
$this->assertEquals($expected, $result);
$this->Number->addFormat('Other', array('before' => '$$ ', 'after' => 'c!'));
$result = $this->Number->currency(0.22, 'Other');
$expected = '22c!';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(-10, 'Other');
$expected = '($$ 10.00)';
$this->assertEquals($expected, $result);
$this->Number->addFormat('Other2', array('before' => '$ ', 'after' => false));
$result = $this->Number->currency(0.22, 'Other2');
$expected = '$ 0.22';
$this->assertEquals($expected,$result);
}
/**
* testCurrencyPositive method
*
* @return void
*/
public function testCurrencyPositive() {
$value = '100100100';
$result = $this->Number->currency($value);
$expected = '$100,100,100.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'USD', array('before' => '#'));
$expected = '#100,100,100.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, false);
$expected = '100,100,100.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'USD');
$expected = '$100,100,100.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'EUR');
$expected = '&#8364;100.100.100,00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'GBP');
$expected = '&#163;100,100,100.00';
$this->assertEquals($expected, $result);
}
/**
* testCurrencyNegative method
*
* @return void
*/
public function testCurrencyNegative() {
$value = '-100100100';
$result = $this->Number->currency($value);
$expected = '($100,100,100.00)';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'EUR');
$expected = '(&#8364;100.100.100,00)';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'GBP');
$expected = '(&#163;100,100,100.00)';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'USD', array('negative' => '-'));
$expected = '-$100,100,100.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'EUR', array('negative' => '-'));
$expected = '-&#8364;100.100.100,00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'GBP', array('negative' => '-'));
$expected = '-&#163;100,100,100.00';
$this->assertEquals($expected, $result);
}
/**
* testCurrencyCentsPositive method
*
* @return void
*/
public function testCurrencyCentsPositive() {
$value = '0.99';
$result = $this->Number->currency($value, 'USD');
$expected = '99c';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'EUR');
$expected = '&#8364;0,99';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'GBP');
$expected = '99p';
$this->assertEquals($expected, $result);
}
/**
* testCurrencyCentsNegative method
*
* @return void
*/
public function testCurrencyCentsNegative() {
$value = '-0.99';
$result = $this->Number->currency($value, 'USD');
$expected = '(99c)';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'EUR');
$expected = '(&#8364;0,99)';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'GBP');
$expected = '(99p)';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'USD', array('negative' => '-'));
$expected = '-99c';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'EUR', array('negative' => '-'));
$expected = '-&#8364;0,99';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'GBP', array('negative' => '-'));
$expected = '-99p';
$this->assertEquals($expected, $result);
}
/**
* testCurrencyZero method
*
* @return void
*/
public function testCurrencyZero() {
$value = '0';
$result = $this->Number->currency($value, 'USD');
$expected = '$0.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'EUR');
$expected = '&#8364;0,00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'GBP');
$expected = '&#163;0.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'GBP', array('zero' => 'FREE!'));
$expected = 'FREE!';
$this->assertEquals($expected, $result);
}
/**
* testCurrencyOptions method
*
* @return void
*/
public function testCurrencyOptions() {
$value = '1234567.89';
$result = $this->Number->currency($value, null, array('before' => 'GBP'));
$expected = 'GBP1,234,567.89';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'GBP', array('places' => 0));
$expected = '&#163;1,234,568';
$this->assertEquals($expected, $result);
$result = $this->Number->currency('1234567.8912345', null, array('before' => 'GBP', 'places' => 3));
$expected = 'GBP1,234,567.891';
$this->assertEquals($expected, $result);
$result = $this->Number->currency('650.120001', null, array('before' => 'GBP', 'places' => 4));
$expected = 'GBP650.1200';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'GBP', array('escape' => true));
$expected = '&amp;#163;1,234,567.89';
$this->assertEquals($expected, $result);
$result = $this->Number->currency('0.35', 'USD', array('after' => false));
$expected = '$0.35';
$this->assertEquals($expected, $result);
$result = $this->Number->currency('0.35', 'GBP', array('after' => false));
$expected = '&#163;0.35';
$this->assertEquals($expected, $result);
$result = $this->Number->currency('0.35', 'GBP');
$expected = '35p';
$this->assertEquals($expected, $result);
$result = $this->Number->currency('0.35', 'EUR');
$expected = '&#8364;0,35';
$this->assertEquals($expected, $result);
}
/**
* testToReadableSize method
*
* @return void
*/
public function testToReadableSize() {
$result = $this->Number->toReadableSize(0);
$expected = '0 Bytes';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1);
$expected = '1 Byte';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(45);
$expected = '45 Bytes';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1023);
$expected = '1023 Bytes';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1024);
$expected = '1 KB';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1024*512);
$expected = '512 KB';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1024*1024-1);
$expected = '1.00 MB';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1024*1024*512);
$expected = '512.00 MB';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1024*1024*1024-1);
$expected = '1.00 GB';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1024*1024*1024*512);
$expected = '512.00 GB';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1024*1024*1024*1024-1);
$expected = '1.00 TB';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1024*1024*1024*1024*512);
$expected = '512.00 TB';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1024*1024*1024*1024*1024-1);
$expected = '1024.00 TB';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1024*1024*1024*1024*1024*1024);
$expected = (1024 * 1024) . '.00 TB';
$this->assertEquals($expected, $result);
}
/**
* testToPercentage method
*
* @return void
*/
public function testToPercentage() {
$result = $this->Number->toPercentage(45, 0);
$expected = '45%';
$this->assertEquals($expected, $result);
$result = $this->Number->toPercentage(45, 2);
$expected = '45.00%';
$this->assertEquals($expected, $result);
$result = $this->Number->toPercentage(0, 0);
$expected = '0%';
$this->assertEquals($expected, $result);
$result = $this->Number->toPercentage(0, 4);
$expected = '0.0000%';
$this->assertEquals($expected, $result);
}
}

View file

@ -0,0 +1,807 @@
<?php
/**
* CakeTimeTest file
*
* PHP 5
*
* CakePHP(tm) Tests <http://book.cakephp.org/view/1196/Testing>
* 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.Test.Case.View.Helper
* @since CakePHP(tm) v 1.2.0.4206
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::uses('CakeTime', 'Utility');
/**
* CakeTimeTest class
*
* @package Cake.Test.Case.View.Helper
*/
class CakeTimeTest extends CakeTestCase {
/**
* setUp method
*
* @return void
*/
public function setUp() {
$this->Time = new CakeTime();
}
/**
* tearDown method
*
* @return void
*/
public function tearDown() {
unset($this->Time);
}
/**
* testToQuarter method
*
* @return void
*/
public function testToQuarter() {
$result = $this->Time->toQuarter('2007-12-25');
$this->assertEquals($result, 4);
$result = $this->Time->toQuarter('2007-9-25');
$this->assertEquals($result, 3);
$result = $this->Time->toQuarter('2007-3-25');
$this->assertEquals($result, 1);
$result = $this->Time->toQuarter('2007-3-25', true);
$this->assertEquals($result, array('2007-01-01', '2007-03-31'));
$result = $this->Time->toQuarter('2007-5-25', true);
$this->assertEquals($result, array('2007-04-01', '2007-06-30'));
$result = $this->Time->toQuarter('2007-8-25', true);
$this->assertEquals($result, array('2007-07-01', '2007-09-30'));
$result = $this->Time->toQuarter('2007-12-25', true);
$this->assertEquals($result, array('2007-10-01', '2007-12-31'));
}
/**
* testTimeAgoInWords method
*
* @return void
*/
public function testTimeAgoInWords() {
$result = $this->Time->timeAgoInWords('-1 week');
$this->assertEquals($result, '1 week ago');
$result = $this->Time->timeAgoInWords('+1 week');
$this->assertEquals($result, '1 week');
$result = $this->Time->timeAgoInWords(strtotime('+4 months +2 weeks +3 days'), array('end' => '8 years'), true);
$this->assertEquals($result, '4 months, 2 weeks, 3 days');
$result = $this->Time->timeAgoInWords(strtotime('+4 months +2 weeks +2 days'), array('end' => '8 years'), true);
$this->assertEquals($result, '4 months, 2 weeks, 2 days');
$result = $this->Time->timeAgoInWords(strtotime('+4 months +2 weeks +1 day'), array('end' => '8 years'), true);
$this->assertEquals($result, '4 months, 2 weeks, 1 day');
$result = $this->Time->timeAgoInWords(strtotime('+3 months +2 weeks +1 day'), array('end' => '8 years'), true);
$this->assertEquals($result, '3 months, 2 weeks, 1 day');
$result = $this->Time->timeAgoInWords(strtotime('+3 months +2 weeks'), array('end' => '8 years'), true);
$this->assertEquals($result, '3 months, 2 weeks');
$result = $this->Time->timeAgoInWords(strtotime('+3 months +1 week +6 days'), array('end' => '8 years'), true);
$this->assertEquals($result, '3 months, 1 week, 6 days');
$result = $this->Time->timeAgoInWords(strtotime('+2 months +2 weeks +1 day'), array('end' => '8 years'), true);
$this->assertEquals($result, '2 months, 2 weeks, 1 day');
$result = $this->Time->timeAgoInWords(strtotime('+2 months +2 weeks'), array('end' => '8 years'), true);
$this->assertEquals($result, '2 months, 2 weeks');
$result = $this->Time->timeAgoInWords(strtotime('+2 months +1 week +6 days'), array('end' => '8 years'), true);
$this->assertEquals($result, '2 months, 1 week, 6 days');
$result = $this->Time->timeAgoInWords(strtotime('+1 month +1 week +6 days'), array('end' => '8 years'), true);
$this->assertEquals($result, '1 month, 1 week, 6 days');
for ($i = 0; $i < 200; $i ++) {
$years = mt_rand(0, 3);
$months = mt_rand(0, 11);
$weeks = mt_rand(0, 3);
$days = mt_rand(0, 6);
$hours = 0;
$minutes = 0;
$seconds = 0;
$relative_date = '';
// Trying to take into account the number of days in a month
$month = date('m') - $months;
if ($month <= 0) {
$month = $months % 12;
}
$time = mktime(0, 0, 0, $month, 1, date('y') - $years);
$diffDays = date('t') - date('t', $time);
if ($diffDays > 0 && date('j') - date('t', $time) - $days > 0 && $months > 0 && $weeks === 0) {
continue;
}
if ($years > 0) {
// years and months and days
$relative_date .= ($relative_date ? ', -' : '-') . $years . ' year' . ($years > 1 ? 's' : '');
$relative_date .= $months > 0 ? ($relative_date ? ', -' : '-') . $months . ' month' . ($months > 1 ? 's' : '') : '';
$relative_date .= $weeks > 0 ? ($relative_date ? ', -' : '-') . $weeks . ' week' . ($weeks > 1 ? 's' : '') : '';
$relative_date .= $days > 0 ? ($relative_date ? ', -' : '-') . $days . ' day' . ($days > 1 ? 's' : '') : '';
} elseif (abs($months) > 0) {
// months, weeks and days
$relative_date .= ($relative_date ? ', -' : '-') . $months . ' month' . ($months > 1 ? 's' : '');
$relative_date .= $weeks > 0 ? ($relative_date ? ', -' : '-') . $weeks . ' week' . ($weeks > 1 ? 's' : '') : '';
$relative_date .= $days > 0 ? ($relative_date ? ', -' : '-') . $days . ' day' . ($days > 1 ? 's' : '') : '';
} elseif (abs($weeks) > 0) {
// weeks and days
$relative_date .= ($relative_date ? ', -' : '-') . $weeks . ' week' . ($weeks > 1 ? 's' : '');
$relative_date .= $days > 0 ? ($relative_date ? ', -' : '-') . $days . ' day' . ($days > 1 ? 's' : '') : '';
} elseif (abs($days) > 0) {
// days and hours
$relative_date .= ($relative_date ? ', -' : '-') . $days . ' day' . ($days > 1 ? 's' : '');
$relative_date .= $hours > 0 ? ($relative_date ? ', -' : '-') . $hours . ' hour' . ($hours > 1 ? 's' : '') : '';
} elseif (abs($hours) > 0) {
// hours and minutes
$relative_date .= ($relative_date ? ', -' : '-') . $hours . ' hour' . ($hours > 1 ? 's' : '');
$relative_date .= $minutes > 0 ? ($relative_date ? ', -' : '-') . $minutes . ' minute' . ($minutes > 1 ? 's' : '') : '';
} elseif (abs($minutes) > 0) {
// minutes only
$relative_date .= ($relative_date ? ', -' : '-') . $minutes . ' minute' . ($minutes > 1 ? 's' : '');
} else {
// seconds only
$relative_date .= ($relative_date ? ', -' : '-') . $seconds . ' second' . ($seconds != 1 ? 's' : '');
}
if (date('j/n/y', strtotime(str_replace(',', '', $relative_date))) != '1/1/70') {
$result = $this->Time->timeAgoInWords(strtotime(str_replace(',', '', $relative_date)), array('end' => '8 years'), true);
if ($relative_date == '0 seconds') {
$relative_date = '0 seconds ago';
}
$relative_date = str_replace('-', '', $relative_date) . ' ago';
$this->assertEquals($result, $relative_date);
}
}
for ($i = 0; $i < 200; $i ++) {
$years = mt_rand(0, 3);
$months = mt_rand(0, 11);
$weeks = mt_rand(0, 3);
$days = mt_rand(0, 6);
$hours = 0;
$minutes = 0;
$seconds = 0;
$relative_date = '';
if ($years > 0) {
// years and months and days
$relative_date .= ($relative_date ? ', ' : '') . $years . ' year' . ($years > 1 ? 's' : '');
$relative_date .= $months > 0 ? ($relative_date ? ', ' : '') . $months . ' month' . ($months > 1 ? 's' : '') : '';
$relative_date .= $weeks > 0 ? ($relative_date ? ', ' : '') . $weeks . ' week' . ($weeks > 1 ? 's' : '') : '';
$relative_date .= $days > 0 ? ($relative_date ? ', ' : '') . $days . ' day' . ($days > 1 ? 's' : '') : '';
} elseif (abs($months) > 0) {
// months, weeks and days
$relative_date .= ($relative_date ? ', ' : '') . $months . ' month' . ($months > 1 ? 's' : '');
$relative_date .= $weeks > 0 ? ($relative_date ? ', ' : '') . $weeks . ' week' . ($weeks > 1 ? 's' : '') : '';
$relative_date .= $days > 0 ? ($relative_date ? ', ' : '') . $days . ' day' . ($days > 1 ? 's' : '') : '';
} elseif (abs($weeks) > 0) {
// weeks and days
$relative_date .= ($relative_date ? ', ' : '') . $weeks . ' week' . ($weeks > 1 ? 's' : '');
$relative_date .= $days > 0 ? ($relative_date ? ', ' : '') . $days . ' day' . ($days > 1 ? 's' : '') : '';
} elseif (abs($days) > 0) {
// days and hours
$relative_date .= ($relative_date ? ', ' : '') . $days . ' day' . ($days > 1 ? 's' : '');
$relative_date .= $hours > 0 ? ($relative_date ? ', ' : '') . $hours . ' hour' . ($hours > 1 ? 's' : '') : '';
} elseif (abs($hours) > 0) {
// hours and minutes
$relative_date .= ($relative_date ? ', ' : '') . $hours . ' hour' . ($hours > 1 ? 's' : '');
$relative_date .= $minutes > 0 ? ($relative_date ? ', ' : '') . $minutes . ' minute' . ($minutes > 1 ? 's' : '') : '';
} elseif (abs($minutes) > 0) {
// minutes only
$relative_date .= ($relative_date ? ', ' : '') . $minutes . ' minute' . ($minutes > 1 ? 's' : '');
} else {
// seconds only
$relative_date .= ($relative_date ? ', ' : '') . $seconds . ' second' . ($seconds != 1 ? 's' : '');
}
if (date('j/n/y', strtotime(str_replace(',', '', $relative_date))) != '1/1/70') {
$result = $this->Time->timeAgoInWords(strtotime(str_replace(',', '', $relative_date)), array('end' => '8 years'), true);
if ($relative_date == '0 seconds') {
$relative_date = '0 seconds ago';
}
$relative_date = str_replace('-', '', $relative_date) . '';
$this->assertEquals($result, $relative_date);
}
}
$result = $this->Time->timeAgoInWords(strtotime('-2 years -5 months -2 days'), array('end' => '3 years'), true);
$this->assertEquals($result, '2 years, 5 months, 2 days ago');
$result = $this->Time->timeAgoInWords('2007-9-25');
$this->assertEquals($result, 'on 25/9/07');
$result = $this->Time->timeAgoInWords('2007-9-25', 'Y-m-d');
$this->assertEquals($result, 'on 2007-09-25');
$result = $this->Time->timeAgoInWords('2007-9-25', 'Y-m-d', true);
$this->assertEquals($result, 'on 2007-09-25');
$result = $this->Time->timeAgoInWords(strtotime('-2 weeks -2 days'), 'Y-m-d', false);
$this->assertEquals($result, '2 weeks, 2 days ago');
$result = $this->Time->timeAgoInWords(strtotime('+2 weeks +2 days'), 'Y-m-d', true);
$this->assertRegExp('/^2 weeks, [1|2] day(s)?$/', $result);
$result = $this->Time->timeAgoInWords(strtotime('+2 months +2 days'), array('end' => '1 month'));
$this->assertEquals($result, 'on ' . date('j/n/y', strtotime('+2 months +2 days')));
$result = $this->Time->timeAgoInWords(strtotime('+2 months +2 days'), array('end' => '3 month'));
$this->assertRegExp('/2 months/', $result);
$result = $this->Time->timeAgoInWords(strtotime('+2 months +12 days'), array('end' => '3 month'));
$this->assertRegExp('/2 months, 1 week/', $result);
$result = $this->Time->timeAgoInWords(strtotime('+3 months +5 days'), array('end' => '4 month'));
$this->assertEquals($result, '3 months, 5 days');
$result = $this->Time->timeAgoInWords(strtotime('-2 months -2 days'), array('end' => '3 month'));
$this->assertEquals($result, '2 months, 2 days ago');
$result = $this->Time->timeAgoInWords(strtotime('-2 months -2 days'), array('end' => '3 month'));
$this->assertEquals($result, '2 months, 2 days ago');
$result = $this->Time->timeAgoInWords(strtotime('+2 months +2 days'), array('end' => '3 month'));
$this->assertRegExp('/2 months/', $result);
$result = $this->Time->timeAgoInWords(strtotime('+2 months +2 days'), array('end' => '1 month', 'format' => 'Y-m-d'));
$this->assertEquals($result, 'on ' . date('Y-m-d', strtotime('+2 months +2 days')));
$result = $this->Time->timeAgoInWords(strtotime('-2 months -2 days'), array('end' => '1 month', 'format' => 'Y-m-d'));
$this->assertEquals($result, 'on ' . date('Y-m-d', strtotime('-2 months -2 days')));
$result = $this->Time->timeAgoInWords(strtotime('-13 months -5 days'), array('end' => '2 years'));
$this->assertEquals($result, '1 year, 1 month, 5 days ago');
$fourHours = $this->Time->timeAgoInWords(strtotime('-5 days -2 hours'), array('userOffset' => -4));
$result = $this->Time->timeAgoInWords(strtotime('-5 days -2 hours'), array('userOffset' => 4));
$this->assertEquals($fourHours, $result);
$result = $this->Time->timeAgoInWords(strtotime('-2 hours'));
$expected = '2 hours ago';
$this->assertEquals($expected, $result);
$result = $this->Time->timeAgoInWords(strtotime('-12 minutes'));
$expected = '12 minutes ago';
$this->assertEquals($expected, $result);
$result = $this->Time->timeAgoInWords(strtotime('-12 seconds'));
$expected = '12 seconds ago';
$this->assertEquals($expected, $result);
$time = strtotime('-3 years -12 months');
$result = $this->Time->timeAgoInWords($time);
$expected = 'on ' . date('j/n/y', $time);
$this->assertEquals($expected, $result);
}
/**
* testNice method
*
* @return void
*/
public function testNice() {
$time = time() + 2 * DAY;
$this->assertEquals(date('D, M jS Y, H:i', $time), $this->Time->nice($time));
$time = time() - 2 * DAY;
$this->assertEquals(date('D, M jS Y, H:i', $time), $this->Time->nice($time));
$time = time();
$this->assertEquals(date('D, M jS Y, H:i', $time), $this->Time->nice($time));
$time = 0;
$this->assertEquals(date('D, M jS Y, H:i', time()), $this->Time->nice($time));
$time = null;
$this->assertEquals(date('D, M jS Y, H:i', time()), $this->Time->nice($time));
$time = time();
$this->assertEquals(date('D', $time), $this->Time->nice($time, null, '%a'));
$this->assertEquals(date('M d, Y', $time), $this->Time->nice($time, null, '%b %d, %Y'));
$this->Time->niceFormat = '%Y-%d-%m';
$this->assertEquals(date('Y-d-m', $time), $this->Time->nice($time));
}
/**
* testNiceShort method
*
* @return void
*/
public function testNiceShort() {
$time = time() + 2 * DAY;
if (date('Y', $time) == date('Y')) {
$this->assertEquals(date('M jS, H:i', $time), $this->Time->niceShort($time));
} else {
$this->assertEquals(date('M jS Y, H:i', $time), $this->Time->niceShort($time));
}
$time = time();
$this->assertEquals('Today, ' . date('H:i', $time), $this->Time->niceShort($time));
$time = time() - DAY;
$this->assertEquals('Yesterday, ' . date('H:i', $time), $this->Time->niceShort($time));
}
/**
* testDaysAsSql method
*
* @return void
*/
public function testDaysAsSql() {
$begin = time();
$end = time() + DAY;
$field = 'my_field';
$expected = '(my_field >= \''.date('Y-m-d', $begin).' 00:00:00\') AND (my_field <= \''.date('Y-m-d', $end).' 23:59:59\')';
$this->assertEquals($expected, $this->Time->daysAsSql($begin, $end, $field));
}
/**
* testDayAsSql method
*
* @return void
*/
public function testDayAsSql() {
$time = time();
$field = 'my_field';
$expected = '(my_field >= \''.date('Y-m-d', $time).' 00:00:00\') AND (my_field <= \''.date('Y-m-d', $time).' 23:59:59\')';
$this->assertEquals($expected, $this->Time->dayAsSql($time, $field));
}
/**
* testToUnix method
*
* @return void
*/
public function testToUnix() {
$this->assertEquals(time(), $this->Time->toUnix(time()));
$this->assertEquals(strtotime('+1 day'), $this->Time->toUnix('+1 day'));
$this->assertEquals(strtotime('+0 days'), $this->Time->toUnix('+0 days'));
$this->assertEquals(strtotime('-1 days'), $this->Time->toUnix('-1 days'));
$this->assertEquals(false, $this->Time->toUnix(''));
$this->assertEquals(false, $this->Time->toUnix(null));
}
/**
* testToAtom method
*
* @return void
*/
public function testToAtom() {
$this->assertEquals(date('Y-m-d\TH:i:s\Z'), $this->Time->toAtom(time()));
}
/**
* testToRss method
*
* @return void
*/
public function testToRss() {
$this->assertEquals(date('r'), $this->Time->toRss(time()));
if (!$this->skipIf(!class_exists('DateTimeZone'), '%s DateTimeZone class not available.')) {
$timezones = array('Europe/London', 'Europe/Brussels', 'UTC', 'America/Denver', 'America/Caracas', 'Asia/Kathmandu');
foreach ($timezones as $timezone) {
$yourTimezone = new DateTimeZone($timezone);
$yourTime = new DateTime('now', $yourTimezone);
$userOffset = $yourTimezone->getOffset($yourTime) / HOUR;
$this->assertEquals($yourTime->format('r'), $this->Time->toRss(time(), $userOffset));
}
}
}
/**
* testFormat method
*
* @return void
*/
public function testFormat() {
$format = 'D-M-Y';
$arr = array(time(), strtotime('+1 days'), strtotime('+1 days'), strtotime('+0 days'));
foreach ($arr as $val) {
$this->assertEquals(date($format, $val), $this->Time->format($format, $val));
}
$result = $this->Time->format('Y-m-d', null, 'never');
$this->assertEquals($result, 'never');
}
/**
* testOfGmt method
*
* @return void
*/
public function testGmt() {
$hour = 3;
$min = 4;
$sec = 2;
$month = 5;
$day = 14;
$year = 2007;
$time = mktime($hour, $min, $sec, $month, $day, $year);
$expected = gmmktime($hour, $min, $sec, $month, $day, $year);
$this->assertEquals($expected, $this->Time->gmt(date('Y-n-j G:i:s', $time)));
$hour = date('H');
$min = date('i');
$sec = date('s');
$month = date('m');
$day = date('d');
$year = date('Y');
$expected = gmmktime($hour, $min, $sec, $month, $day, $year);
$this->assertEquals($expected, $this->Time->gmt(null));
}
/**
* testIsToday method
*
* @return void
*/
public function testIsToday() {
$result = $this->Time->isToday('+1 day');
$this->assertFalse($result);
$result = $this->Time->isToday('+1 days');
$this->assertFalse($result);
$result = $this->Time->isToday('+0 day');
$this->assertTrue($result);
$result = $this->Time->isToday('-1 day');
$this->assertFalse($result);
}
/**
* testIsThisWeek method
*
* @return void
*/
public function testIsThisWeek() {
// A map of days which goes from -1 day of week to +1 day of week
$map = array(
'Mon' => array(-1, 7), 'Tue' => array(-2, 6), 'Wed' => array(-3, 5),
'Thu' => array(-4, 4), 'Fri' => array(-5, 3), 'Sat' => array(-6, 2),
'Sun' => array(-7, 1)
);
$days = $map[date('D')];
for ($day = $days[0] + 1; $day < $days[1]; $day++) {
$this->assertTrue($this->Time->isThisWeek(($day > 0 ? '+' : '') . $day . ' days'));
}
$this->assertFalse($this->Time->isThisWeek($days[0] . ' days'));
$this->assertFalse($this->Time->isThisWeek('+' . $days[1] . ' days'));
}
/**
* testIsThisMonth method
*
* @return void
*/
public function testIsThisMonth() {
$result = $this->Time->isThisMonth('+0 day');
$this->assertTrue($result);
$result = $this->Time->isThisMonth($time = mktime(0, 0, 0, date('m'), mt_rand(1, 28), date('Y')));
$this->assertTrue($result);
$result = $this->Time->isThisMonth(mktime(0, 0, 0, date('m'), mt_rand(1, 28), date('Y') - mt_rand(1, 12)));
$this->assertFalse($result);
$result = $this->Time->isThisMonth(mktime(0, 0, 0, date('m'), mt_rand(1, 28), date('Y') + mt_rand(1, 12)));
$this->assertFalse($result);
}
/**
* testIsThisYear method
*
* @return void
*/
public function testIsThisYear() {
$result = $this->Time->isThisYear('+0 day');
$this->assertTrue($result);
$result = $this->Time->isThisYear(mktime(0, 0, 0, mt_rand(1, 12), mt_rand(1, 28), date('Y')));
$this->assertTrue($result);
}
/**
* testWasYesterday method
*
* @return void
*/
public function testWasYesterday() {
$result = $this->Time->wasYesterday('+1 day');
$this->assertFalse($result);
$result = $this->Time->wasYesterday('+1 days');
$this->assertFalse($result);
$result = $this->Time->wasYesterday('+0 day');
$this->assertFalse($result);
$result = $this->Time->wasYesterday('-1 day');
$this->assertTrue($result);
$result = $this->Time->wasYesterday('-1 days');
$this->assertTrue($result);
$result = $this->Time->wasYesterday('-2 days');
$this->assertFalse($result);
}
/**
* testIsTomorrow method
*
* @return void
*/
public function testIsTomorrow() {
$result = $this->Time->isTomorrow('+1 day');
$this->assertTrue($result);
$result = $this->Time->isTomorrow('+1 days');
$this->assertTrue($result);
$result = $this->Time->isTomorrow('+0 day');
$this->assertFalse($result);
$result = $this->Time->isTomorrow('-1 day');
$this->assertFalse($result);
}
/**
* testWasWithinLast method
*
* @return void
*/
public function testWasWithinLast() {
$this->assertTrue($this->Time->wasWithinLast('1 day', '-1 day'));
$this->assertTrue($this->Time->wasWithinLast('1 week', '-1 week'));
$this->assertTrue($this->Time->wasWithinLast('1 year', '-1 year'));
$this->assertTrue($this->Time->wasWithinLast('1 second', '-1 second'));
$this->assertTrue($this->Time->wasWithinLast('1 minute', '-1 minute'));
$this->assertTrue($this->Time->wasWithinLast('1 year', '-1 year'));
$this->assertTrue($this->Time->wasWithinLast('1 month', '-1 month'));
$this->assertTrue($this->Time->wasWithinLast('1 day', '-1 day'));
$this->assertTrue($this->Time->wasWithinLast('1 week', '-1 day'));
$this->assertTrue($this->Time->wasWithinLast('2 week', '-1 week'));
$this->assertFalse($this->Time->wasWithinLast('1 second', '-1 year'));
$this->assertTrue($this->Time->wasWithinLast('10 minutes', '-1 second'));
$this->assertTrue($this->Time->wasWithinLast('23 minutes', '-1 minute'));
$this->assertFalse($this->Time->wasWithinLast('0 year', '-1 year'));
$this->assertTrue($this->Time->wasWithinLast('13 month', '-1 month'));
$this->assertTrue($this->Time->wasWithinLast('2 days', '-1 day'));
$this->assertFalse($this->Time->wasWithinLast('1 week', '-2 weeks'));
$this->assertFalse($this->Time->wasWithinLast('1 second', '-2 seconds'));
$this->assertFalse($this->Time->wasWithinLast('1 day', '-2 days'));
$this->assertFalse($this->Time->wasWithinLast('1 hour', '-2 hours'));
$this->assertFalse($this->Time->wasWithinLast('1 month', '-2 months'));
$this->assertFalse($this->Time->wasWithinLast('1 year', '-2 years'));
$this->assertFalse($this->Time->wasWithinLast('1 day', '-2 weeks'));
$this->assertFalse($this->Time->wasWithinLast('1 day', '-2 days'));
$this->assertFalse($this->Time->wasWithinLast('0 days', '-2 days'));
$this->assertTrue($this->Time->wasWithinLast('1 hour', '-20 seconds'));
$this->assertTrue($this->Time->wasWithinLast('1 year', '-60 minutes -30 seconds'));
$this->assertTrue($this->Time->wasWithinLast('3 years', '-2 months'));
$this->assertTrue($this->Time->wasWithinLast('5 months', '-4 months'));
$this->assertTrue($this->Time->wasWithinLast('5 ', '-3 days'));
$this->assertTrue($this->Time->wasWithinLast('1 ', '-1 hour'));
$this->assertTrue($this->Time->wasWithinLast('1 ', '-1 minute'));
$this->assertTrue($this->Time->wasWithinLast('1 ', '-23 hours -59 minutes -59 seconds'));
}
/**
* testUserOffset method
*
* @return void
*/
public function testUserOffset() {
$timezoneServer = new DateTimeZone(date_default_timezone_get());
$timeServer = new DateTime('now', $timezoneServer);
$yourTimezone = $timezoneServer->getOffset($timeServer) / HOUR;
$expected = time();
$result = $this->Time->fromString(time(), $yourTimezone);
$this->assertEquals($expected, $result);
}
/**
* test fromString()
*
* @return void
*/
public function testFromString() {
$result = $this->Time->fromString('');
$this->assertFalse($result);
$result = $this->Time->fromString(0, 0);
$this->assertFalse($result);
$result = $this->Time->fromString('+1 hour');
$expected = strtotime('+1 hour');
$this->assertEquals($expected, $result);
$timezone = date('Z', time());
$result = $this->Time->fromString('+1 hour', $timezone);
$expected = $this->Time->convert(strtotime('+1 hour'), $timezone);
$this->assertEquals($expected, $result);
}
/**
* test converting time specifiers using a time definition localfe file
*
* @return void
*/
public function testConvertSpecifiers() {
App::build(array(
'locales' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Locale' . DS)
), true);
Configure::write('Config.language', 'time_test');
$time = strtotime('Thu Jan 14 11:43:39 2010');
$result = $this->Time->convertSpecifiers('%a', $time);
$expected = 'jue';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%A', $time);
$expected = 'jueves';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%c', $time);
$expected = 'jue %d ene %Y %H:%M:%S %Z';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%C', $time);
$expected = '20';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%D', $time);
$expected = '%m/%d/%y';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%b', $time);
$expected = 'ene';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%h', $time);
$expected = 'ene';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%B', $time);
$expected = 'enero';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%n', $time);
$expected = "\n";
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%n', $time);
$expected = "\n";
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%p', $time);
$expected = 'AM';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%P', $time);
$expected = 'am';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%r', $time);
$expected = '%I:%M:%S AM';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%R', $time);
$expected = '11:43';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%t', $time);
$expected = "\t";
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%T', $time);
$expected = '%H:%M:%S';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%u', $time);
$expected = 4;
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%x', $time);
$expected = '%d/%m/%y';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%X', $time);
$expected = '%H:%M:%S';
$this->assertEquals($expected, $result);
}
/**
* test convert %e on windows.
*
* @return void
*/
public function testConvertPercentE() {
$this->skipIf(DIRECTORY_SEPARATOR !== '\\', 'Cannot run windows tests on non-windows OS.');
$time = strtotime('Thu Jan 14 11:43:39 2010');
$result = $this->Time->convertSpecifiers('%e', $time);
$expected = '14';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%e', strtotime('2011-01-01'));
$expected = ' 1';
$this->assertEquals($expected, $result);
}
/**
* test formatting dates taking in account preferred i18n locale file
*
* @return void
*/
public function testI18nFormat() {
App::build(array(
'locales' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Locale' . DS)
), true);
Configure::write('Config.language', 'time_test');
$time = strtotime('Thu Jan 14 13:59:28 2010');
$result = $this->Time->i18nFormat($time);
$expected = '14/01/10';
$this->assertEquals($expected, $result);
$result = $this->Time->i18nFormat($time, '%c');
$expected = 'jue 14 ene 2010 13:59:28 ' . strftime('%Z', $time);
$this->assertEquals($expected, $result);
$result = $this->Time->i18nFormat($time, 'Time is %r, and date is %x');
$expected = 'Time is 01:59:28 PM, and date is 14/01/10';
$this->assertEquals($expected, $result);
$time = strtotime('Wed Jan 13 13:59:28 2010');
$result = $this->Time->i18nFormat($time);
$expected = '13/01/10';
$this->assertEquals($expected, $result);
$result = $this->Time->i18nFormat($time, '%c');
$expected = 'mié 13 ene 2010 13:59:28 ' . strftime('%Z', $time);
$this->assertEquals($expected, $result);
$result = $this->Time->i18nFormat($time, 'Time is %r, and date is %x');
$expected = 'Time is 01:59:28 PM, and date is 13/01/10';
$this->assertEquals($expected, $result);
$result = $this->Time->i18nFormat('invalid date', '%x', 'Date invalid');
$expected = 'Date invalid';
$this->assertEquals($expected, $result);
}
/**
* test new format() syntax which inverts first and secod parameters
*
* @return void
*/
public function testFormatNewSyntax() {
$time = time();
$this->assertEquals($this->Time->format($time), $this->Time->i18nFormat($time));
$this->assertEquals($this->Time->format($time, '%c'), $this->Time->i18nFormat($time, '%c'));
}
}

View file

@ -25,6 +25,16 @@ App::uses('String', 'Utility');
*/
class StringTest extends CakeTestCase {
public function setUp() {
parent::setUp();
$this->Text = new String();
}
public function tearDown() {
parent::tearDown();
unset($this->Text);
}
/**
* testUuidGeneration method
*
@ -344,4 +354,291 @@ This is the song that never ends.
TEXT;
$this->assertTextEquals($expected, $result);
}
/**
* testTruncate method
*
* @return void
*/
public function testTruncate() {
$text1 = 'The quick brown fox jumps over the lazy dog';
$text2 = 'Heiz&ouml;lr&uuml;cksto&szlig;abd&auml;mpfung';
$text3 = '<b>&copy; 2005-2007, Cake Software Foundation, Inc.</b><br />written by Alexander Wegener';
$text4 = '<img src="mypic.jpg"> This image tag is not XHTML conform!<br><hr/><b>But the following image tag should be conform <img src="mypic.jpg" alt="Me, myself and I" /></b><br />Great, or?';
$text5 = '0<b>1<i>2<span class="myclass">3</span>4<u>5</u>6</i>7</b>8<b>9</b>0';
$text6 = '<p><strong>Extra dates have been announced for this year\'s tour.</strong></p><p>Tickets for the new shows in</p>';
$text7 = 'El moño está en el lugar correcto. Eso fue lo que dijo la niña, ¿habrá dicho la verdad?';
$text8 = 'Vive la R' . chr(195) . chr(169) . 'publique de France';
$text9 = 'НОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыь';
$this->assertSame($this->Text->truncate($text1, 15), 'The quick br...');
$this->assertSame($this->Text->truncate($text1, 15, array('exact' => false)), 'The quick...');
$this->assertSame($this->Text->truncate($text1, 100), 'The quick brown fox jumps over the lazy dog');
$this->assertSame($this->Text->truncate($text2, 10), 'Heiz&ou...');
$this->assertSame($this->Text->truncate($text2, 10, array('exact' => false)), '...');
$this->assertSame($this->Text->truncate($text3, 20), '<b>&copy; 2005-20...');
$this->assertSame($this->Text->truncate($text4, 15), '<img src="my...');
$this->assertSame($this->Text->truncate($text5, 6, array('ending' => '')), '0<b>1<');
$this->assertSame($this->Text->truncate($text1, 15, array('html' => true)), 'The quick br...');
$this->assertSame($this->Text->truncate($text1, 15, array('exact' => false, 'html' => true)), 'The quick...');
$this->assertSame($this->Text->truncate($text2, 10, array('html' => true)), 'Heiz&ouml;lr...');
$this->assertSame($this->Text->truncate($text2, 10, array('exact' => false, 'html' => true)), '...');
$this->assertSame($this->Text->truncate($text3, 20, array('html' => true)), '<b>&copy; 2005-2007, Cake...</b>');
$this->assertSame($this->Text->truncate($text4, 15, array('html' => true)), '<img src="mypic.jpg"> This image ...');
$this->assertSame($this->Text->truncate($text4, 45, array('html' => true)), '<img src="mypic.jpg"> This image tag is not XHTML conform!<br><hr/><b>But t...</b>');
$this->assertSame($this->Text->truncate($text4, 90, array('html' => true)), '<img src="mypic.jpg"> This image tag is not XHTML conform!<br><hr/><b>But the following image tag should be conform <img src="mypic.jpg" alt="Me, myself and I" /></b><br />Grea...');
$this->assertSame($this->Text->truncate($text5, 6, array('ending' => '', 'html' => true)), '0<b>1<i>2<span class="myclass">3</span>4<u>5</u></i></b>');
$this->assertSame($this->Text->truncate($text5, 20, array('ending' => '', 'html' => true)), $text5);
$this->assertSame($this->Text->truncate($text6, 57, array('exact' => false, 'html' => true)), "<p><strong>Extra dates have been announced for this year's...</strong></p>");
$this->assertSame($this->Text->truncate($text7, 255), $text7);
$this->assertSame($this->Text->truncate($text7, 15), 'El moño está...');
$this->assertSame($this->Text->truncate($text8, 15), 'Vive la R'.chr(195).chr(169).'pu...');
$this->assertSame($this->Text->truncate($text9, 10), 'НОПРСТУ...');
$text = '<p><span style="font-size: medium;"><a>Iamatestwithnospacesandhtml</a></span></p>';
$result = $this->Text->truncate($text, 10, array(
'ending' => '...',
'exact' => false,
'html' => true
));
$expected = '<p><span style="font-size: medium;"><a>...</a></span></p>';
$this->assertEquals($expected, $result);
$text = '<p><span style="font-size: medium;">El biógrafo de Steve Jobs, Walter
Isaacson, explica porqué Jobs le pidió que le hiciera su biografía en
este artículo de El País.</span></p>
<p><span style="font-size: medium;"><span style="font-size:
large;">Por qué Steve era distinto.</span></span></p>
<p><span style="font-size: medium;"><a href="http://www.elpais.com/
articulo/primer/plano/Steve/era/distinto/elpepueconeg/
20111009elpneglse_4/Tes">http://www.elpais.com/articulo/primer/plano/
Steve/era/distinto/elpepueconeg/20111009elpneglse_4/Tes</a></span></p>
<p><span style="font-size: medium;">Ya se ha publicado la biografía de
Steve Jobs escrita por Walter Isaacson "<strong>Steve Jobs by Walter
Isaacson</strong>", aquí os dejamos la dirección de amazon donde
podeís adquirirla.</span></p>
<p><span style="font-size: medium;"><a>http://www.amazon.com/Steve-
Jobs-Walter-Isaacson/dp/1451648537</a></span></p>';
$result = $this->Text->truncate($text, 500, array(
'ending' => '... ',
'exact' => false,
'html' => true
));
$expected = '<p><span style="font-size: medium;">El biógrafo de Steve Jobs, Walter
Isaacson, explica porqué Jobs le pidió que le hiciera su biografía en
este artículo de El País.</span></p>
<p><span style="font-size: medium;"><span style="font-size:
large;">Por qué Steve era distinto.</span></span></p>
<p><span style="font-size: medium;"><a href="http://www.elpais.com/
articulo/primer/plano/Steve/era/distinto/elpepueconeg/
20111009elpneglse_4/Tes">http://www.elpais.com/articulo/primer/plano/
Steve/era/distinto/elpepueconeg/20111009elpneglse_4/Tes</a></span></p>
<p><span style="font-size: medium;">Ya se ha publicado la biografía de
Steve Jobs escrita por Walter Isaacson "<strong>Steve Jobs by Walter
Isaacson</strong>", aquí os dejamos la dirección de amazon donde
podeís adquirirla.</span></p>
<p><span style="font-size: medium;"><a>... </a></span></p>';
$this->assertEquals($expected, $result);
}
/**
* testHighlight method
*
* @return void
*/
public function testHighlight() {
$text = 'This is a test text';
$phrases = array('This', 'text');
$result = $this->Text->highlight($text, $phrases, array('format' => '<b>\1</b>'));
$expected = '<b>This</b> is a test <b>text</b>';
$this->assertEquals($expected, $result);
$text = 'This is a test text';
$phrases = null;
$result = $this->Text->highlight($text, $phrases, array('format' => '<b>\1</b>'));
$this->assertEquals($result, $text);
$text = 'This is a (test) text';
$phrases = '(test';
$result = $this->Text->highlight($text, $phrases, array('format' => '<b>\1</b>'));
$this->assertEquals('This is a <b>(test</b>) text', $result);
$text = 'Ich saß in einem Café am Übergang';
$expected = 'Ich <b>saß</b> in einem <b>Café</b> am <b>Übergang</b>';
$phrases = array('saß', 'café', 'übergang');
$result = $this->Text->highlight($text, $phrases, array('format' => '<b>\1</b>'));
$this->assertEquals($expected, $result);
}
/**
* testHighlightHtml method
*
* @return void
*/
public function testHighlightHtml() {
$text1 = '<p>strongbow isn&rsquo;t real cider</p>';
$text2 = '<p>strongbow <strong>isn&rsquo;t</strong> real cider</p>';
$text3 = '<img src="what-a-strong-mouse.png" alt="What a strong mouse!" />';
$text4 = 'What a strong mouse: <img src="what-a-strong-mouse.png" alt="What a strong mouse!" />';
$options = array('format' => '<b>\1</b>', 'html' => true);
$expected = '<p><b>strong</b>bow isn&rsquo;t real cider</p>';
$this->assertEquals($this->Text->highlight($text1, 'strong', $options), $expected);
$expected = '<p><b>strong</b>bow <strong>isn&rsquo;t</strong> real cider</p>';
$this->assertEquals($this->Text->highlight($text2, 'strong', $options), $expected);
$this->assertEquals($this->Text->highlight($text3, 'strong', $options), $text3);
$this->assertEquals($this->Text->highlight($text3, array('strong', 'what'), $options), $text3);
$expected = '<b>What</b> a <b>strong</b> mouse: <img src="what-a-strong-mouse.png" alt="What a strong mouse!" />';
$this->assertEquals($this->Text->highlight($text4, array('strong', 'what'), $options), $expected);
}
/**
* testHighlightMulti method
*
* @return void
*/
public function testHighlightMulti() {
$text = 'This is a test text';
$phrases = array('This', 'text');
$result = $this->Text->highlight($text, $phrases, array('format' => array('<b>\1</b>', '<em>\1</em>')));
$expected = '<b>This</b> is a test <em>text</em>';
$this->assertEquals($expected, $result);
}
/**
* testStripLinks method
*
* @return void
*/
public function testStripLinks() {
$text = 'This is a test text';
$expected = 'This is a test text';
$result = $this->Text->stripLinks($text);
$this->assertEquals($expected, $result);
$text = 'This is a <a href="#">test</a> text';
$expected = 'This is a test text';
$result = $this->Text->stripLinks($text);
$this->assertEquals($expected, $result);
$text = 'This <strong>is</strong> a <a href="#">test</a> <a href="#">text</a>';
$expected = 'This <strong>is</strong> a test text';
$result = $this->Text->stripLinks($text);
$this->assertEquals($expected, $result);
$text = 'This <strong>is</strong> a <a href="#">test</a> and <abbr>some</abbr> other <a href="#">text</a>';
$expected = 'This <strong>is</strong> a test and <abbr>some</abbr> other text';
$result = $this->Text->stripLinks($text);
$this->assertEquals($expected, $result);
}
/**
* testHighlightCaseInsensitivity method
*
* @return void
*/
public function testHighlightCaseInsensitivity() {
$text = 'This is a Test text';
$expected = 'This is a <b>Test</b> text';
$result = $this->Text->highlight($text, 'test', array('format' => '<b>\1</b>'));
$this->assertEquals($expected, $result);
$result = $this->Text->highlight($text, array('test'), array('format' => '<b>\1</b>'));
$this->assertEquals($expected, $result);
}
/**
* testExcerpt method
*
* @return void
*/
public function testExcerpt() {
$text = 'This is a phrase with test text to play with';
$expected = '...ase with test text to ...';
$result = $this->Text->excerpt($text, 'test', 9, '...');
$this->assertEquals($expected, $result);
$expected = 'This is a...';
$result = $this->Text->excerpt($text, 'not_found', 9, '...');
$this->assertEquals($expected, $result);
$expected = 'This is a phras...';
$result = $this->Text->excerpt($text, null, 9, '...');
$this->assertEquals($expected, $result);
$expected = $text;
$result = $this->Text->excerpt($text, null, 200, '...');
$this->assertEquals($expected, $result);
$expected = '...a phrase w...';
$result = $this->Text->excerpt($text, 'phrase', 2, '...');
$this->assertEquals($expected, $result);
$phrase = 'This is a phrase with test text';
$expected = $text;
$result = $this->Text->excerpt($text, $phrase, 13, '...');
$this->assertEquals($expected, $result);
$text = 'aaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaa';
$phrase = 'bbbbbbbb';
$result = $this->Text->excerpt($text, $phrase, 10);
$expected = '...aaaaaaaaaabbbbbbbbaaaaaaaaaa...';
$this->assertEquals($expected, $result);
}
/**
* testExcerptCaseInsensitivity method
*
* @return void
*/
public function testExcerptCaseInsensitivity() {
$text = 'This is a phrase with test text to play with';
$expected = '...ase with test text to ...';
$result = $this->Text->excerpt($text, 'TEST', 9, '...');
$this->assertEquals($expected, $result);
$expected = 'This is a...';
$result = $this->Text->excerpt($text, 'NOT_FOUND', 9, '...');
$this->assertEquals($expected, $result);
}
/**
* testListGeneration method
*
* @return void
*/
public function testListGeneration() {
$result = $this->Text->toList(array());
$this->assertEquals($result, '');
$result = $this->Text->toList(array('One'));
$this->assertEquals($result, 'One');
$result = $this->Text->toList(array('Larry', 'Curly', 'Moe'));
$this->assertEquals($result, 'Larry, Curly and Moe');
$result = $this->Text->toList(array('Dusty', 'Lucky', 'Ned'), 'y');
$this->assertEquals($result, 'Dusty, Lucky y Ned');
$result = $this->Text->toList(array(1 => 'Dusty', 2 => 'Lucky', 3 => 'Ned'), 'y');
$this->assertEquals($result, 'Dusty, Lucky y Ned');
$result = $this->Text->toList(array(1 => 'Dusty', 2 => 'Lucky', 3 => 'Ned'), 'and', ' + ');
$this->assertEquals($result, 'Dusty + Lucky and Ned');
$result = $this->Text->toList(array('name1' => 'Dusty', 'name2' => 'Lucky'));
$this->assertEquals($result, 'Dusty and Lucky');
$result = $this->Text->toList(array('test_0' => 'banana', 'test_1' => 'apple', 'test_2' => 'lemon'));
$this->assertEquals($result, 'banana, apple and lemon');
}
}

View file

@ -1462,6 +1462,31 @@ class FormHelperTest extends CakeTestCase {
$this->assertEquals(array(), $this->Form->fields);
}
/**
* testTagIsInvalid method
*
* @return void
*/
public function testTagIsInvalid() {
$Contact = ClassRegistry::getObject('Contact');
$Contact->validationErrors[0]['email'] = array('Please provide an email');
$this->Form->setEntity('Contact.0.email');
$result = $this->Form->tagIsInvalid();
$expected = array('Please provide an email');
$this->assertEquals($expected, $result);
$this->Form->setEntity('Contact.1.email');
$result = $this->Form->tagIsInvalid();
$expected = false;
$this->assertIdentical($expected, $result);
$this->Form->setEntity('Contact.0.name');
$result = $this->Form->tagIsInvalid();
$expected = false;
$this->assertIdentical($expected, $result);
}
/**
* testPasswordValidation method
*

View file

@ -1725,7 +1725,7 @@ class HtmlHelperTest extends CakeTestCase {
);
$this->assertTags($result, $expected);
$result = $this->Html->media('video.ogv', array('type' => 'video'));
$result = $this->Html->media('video.ogv', array('tag' => 'video'));
$expected = array('video' => array('src' => 'files/video.ogv'), '/video');
$this->assertTags($result, $expected);
@ -1743,6 +1743,13 @@ class HtmlHelperTest extends CakeTestCase {
'/video'
);
$this->assertTags($result, $expected);
$result = $this->Html->media(null, array('src' => 'video.webm'));
$expected = array(
'video' => array('src' => 'files/video.webm'),
'/video'
);
$this->assertTags($result, $expected);
}
/**

View file

@ -20,6 +20,17 @@
App::uses('View', 'View');
App::uses('NumberHelper', 'View/Helper');
/**
* NumberHelperTestObject class
*/
class NumberHelperTestObject extends NumberHelper {
public function attach(CakeNumber $cakeNumber) {
$this->_CakeNumber = $cakeNumber;
}
}
/**
* NumberHelperTest class
*
@ -27,13 +38,6 @@ App::uses('NumberHelper', 'View/Helper');
*/
class NumberHelperTest extends CakeTestCase {
/**
* helper property
*
* @var mixed null
*/
public $helper = null;
/**
* setUp method
*
@ -42,7 +46,9 @@ class NumberHelperTest extends CakeTestCase {
public function setUp() {
parent::setUp();
$view = $this->getMock('View', array(), array(), '', false);
$this->Number = new NumberHelper($view);
$this->CakeNumber = $this->getMock('CakeNumber');
$this->Number = new NumberHelperTestObject($view);
$this->Number->attach($this->CakeNumber);
}
/**
@ -55,416 +61,19 @@ class NumberHelperTest extends CakeTestCase {
unset($this->Number);
}
/**
* testFormatAndCurrency method
*
* @return void
*/
public function testFormat() {
$value = '100100100';
$result = $this->Number->format($value, '#');
$expected = '#100,100,100';
$this->assertEquals($expected, $result);
$result = $this->Number->format($value, 3);
$expected = '100,100,100.000';
$this->assertEquals($expected, $result);
$result = $this->Number->format($value);
$expected = '100,100,100';
$this->assertEquals($expected, $result);
$result = $this->Number->format($value, '-');
$expected = '100-100-100';
$this->assertEquals($expected, $result);
}
/**
* Test currency method.
*
* @return void
* test CakeNumber class methods are called correctly
*/
public function testCurrency() {
$value = '100100100';
$result = $this->Number->currency($value);
$expected = '$100,100,100.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, '#');
$expected = '#100,100,100.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, false);
$expected = '100,100,100.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'USD');
$expected = '$100,100,100.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'EUR');
$expected = '&#8364;100.100.100,00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'GBP');
$expected = '&#163;100,100,100.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, '', array('thousands' => ' ', 'wholeSymbol' => '€', 'wholePosition' => 'after', 'decimals' => ',', 'zero' => 'Gratuit'));
$expected = '100 100 100,00€';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(1000.45, NULL, array('after' => 'øre', 'before' => 'Kr. ', 'decimals' => ',', 'thousands' => '.'));
$expected = 'Kr. 1.000,45';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(0.5, 'USD');
$expected = '50c';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(0.5, NULL, array('after' => 'øre'));
$expected = '50øre';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(1, null, array('wholeSymbol' => '$ '));
$expected = '$ 1.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(1, null, array('wholeSymbol' => ' $', 'wholePosition' => 'after'));
$expected = '1.00 $';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(0.2, null, array('wholeSymbol' => ' $', 'wholePosition' => 'after', 'fractionSymbol' => 'cents'));
$expected = '20cents';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(0.2, null, array('wholeSymbol' => ' $', 'wholePosition' => 'after', 'fractionSymbol' => 'cents', 'fractionPosition' => 'before'));
$expected = 'cents20';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(311, 'USD', array('wholePosition' => 'after'));
$expected = '311.00$';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(0.2, 'EUR');
$expected = '&#8364;0,20';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(12, null, array('wholeSymbol' => ' dollars', 'wholePosition' => 'after', 'fractionSymbol' => ' cents', 'fractionPosition' => 'after'));
$expected = '12.00 dollars';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(0.12, null, array('wholeSymbol' => ' dollars', 'wholePosition' => 'after', 'fractionSymbol' => ' cents', 'fractionPosition' => 'after'));
$expected = '12 cents';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(0.5, null, array('fractionSymbol' => false, 'fractionPosition' => 'before', 'wholeSymbol' => '$'));
$expected = '$0.50';
$this->assertEquals($expected, $result);
public function testNumberHelperProxyMethodCalls() {
$methods = array(
'precision', 'toReadableSize', 'toPercentage', 'format',
'currency', 'addFormat',
);
foreach ($methods as $method) {
$this->CakeNumber->expects($this->at(0))->method($method);
$this->Number->{$method}('who', 'what', 'when', 'where', 'how');
}
}
/**
* Test adding currency format options to the number helper
*
* @return void
*/
public function testCurrencyAddFormat() {
$this->Number->addFormat('NOK', array('before' => 'Kr. '));
$result = $this->Number->currency(1000, 'NOK');
$expected = 'Kr. 1,000.00';
$this->assertEquals($expected, $result);
$this->Number->addFormat('Other', array('before' => '$$ ', 'after' => 'c!'));
$result = $this->Number->currency(0.22, 'Other');
$expected = '22c!';
$this->assertEquals($expected, $result);
$result = $this->Number->currency(-10, 'Other');
$expected = '($$ 10.00)';
$this->assertEquals($expected, $result);
$this->Number->addFormat('Other2', array('before' => '$ ', 'after' => false));
$result = $this->Number->currency(0.22, 'Other2');
$expected = '$ 0.22';
$this->assertEquals($expected,$result);
}
/**
* testCurrencyPositive method
*
* @return void
*/
public function testCurrencyPositive() {
$value = '100100100';
$result = $this->Number->currency($value);
$expected = '$100,100,100.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'USD', array('before' => '#'));
$expected = '#100,100,100.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, false);
$expected = '100,100,100.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'USD');
$expected = '$100,100,100.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'EUR');
$expected = '&#8364;100.100.100,00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'GBP');
$expected = '&#163;100,100,100.00';
$this->assertEquals($expected, $result);
}
/**
* testCurrencyNegative method
*
* @return void
*/
public function testCurrencyNegative() {
$value = '-100100100';
$result = $this->Number->currency($value);
$expected = '($100,100,100.00)';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'EUR');
$expected = '(&#8364;100.100.100,00)';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'GBP');
$expected = '(&#163;100,100,100.00)';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'USD', array('negative' => '-'));
$expected = '-$100,100,100.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'EUR', array('negative' => '-'));
$expected = '-&#8364;100.100.100,00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'GBP', array('negative' => '-'));
$expected = '-&#163;100,100,100.00';
$this->assertEquals($expected, $result);
}
/**
* testCurrencyCentsPositive method
*
* @return void
*/
public function testCurrencyCentsPositive() {
$value = '0.99';
$result = $this->Number->currency($value, 'USD');
$expected = '99c';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'EUR');
$expected = '&#8364;0,99';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'GBP');
$expected = '99p';
$this->assertEquals($expected, $result);
}
/**
* testCurrencyCentsNegative method
*
* @return void
*/
public function testCurrencyCentsNegative() {
$value = '-0.99';
$result = $this->Number->currency($value, 'USD');
$expected = '(99c)';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'EUR');
$expected = '(&#8364;0,99)';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'GBP');
$expected = '(99p)';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'USD', array('negative' => '-'));
$expected = '-99c';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'EUR', array('negative' => '-'));
$expected = '-&#8364;0,99';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'GBP', array('negative' => '-'));
$expected = '-99p';
$this->assertEquals($expected, $result);
}
/**
* testCurrencyZero method
*
* @return void
*/
public function testCurrencyZero() {
$value = '0';
$result = $this->Number->currency($value, 'USD');
$expected = '$0.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'EUR');
$expected = '&#8364;0,00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'GBP');
$expected = '&#163;0.00';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'GBP', array('zero' => 'FREE!'));
$expected = 'FREE!';
$this->assertEquals($expected, $result);
}
/**
* testCurrencyOptions method
*
* @return void
*/
public function testCurrencyOptions() {
$value = '1234567.89';
$result = $this->Number->currency($value, null, array('before' => 'GBP'));
$expected = 'GBP1,234,567.89';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'GBP', array('places' => 0));
$expected = '&#163;1,234,568';
$this->assertEquals($expected, $result);
$result = $this->Number->currency('1234567.8912345', null, array('before' => 'GBP', 'places' => 3));
$expected = 'GBP1,234,567.891';
$this->assertEquals($expected, $result);
$result = $this->Number->currency('650.120001', null, array('before' => 'GBP', 'places' => 4));
$expected = 'GBP650.1200';
$this->assertEquals($expected, $result);
$result = $this->Number->currency($value, 'GBP', array('escape' => true));
$expected = '&amp;#163;1,234,567.89';
$this->assertEquals($expected, $result);
$result = $this->Number->currency('0.35', 'USD', array('after' => false));
$expected = '$0.35';
$this->assertEquals($expected, $result);
$result = $this->Number->currency('0.35', 'GBP', array('after' => false));
$expected = '&#163;0.35';
$this->assertEquals($expected, $result);
$result = $this->Number->currency('0.35', 'GBP');
$expected = '35p';
$this->assertEquals($expected, $result);
$result = $this->Number->currency('0.35', 'EUR');
$expected = '&#8364;0,35';
$this->assertEquals($expected, $result);
}
/**
* testToReadableSize method
*
* @return void
*/
public function testToReadableSize() {
$result = $this->Number->toReadableSize(0);
$expected = '0 Bytes';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1);
$expected = '1 Byte';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(45);
$expected = '45 Bytes';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1023);
$expected = '1023 Bytes';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1024);
$expected = '1 KB';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1024*512);
$expected = '512 KB';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1024*1024-1);
$expected = '1.00 MB';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1024*1024*512);
$expected = '512.00 MB';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1024*1024*1024-1);
$expected = '1.00 GB';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1024*1024*1024*512);
$expected = '512.00 GB';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1024*1024*1024*1024-1);
$expected = '1.00 TB';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1024*1024*1024*1024*512);
$expected = '512.00 TB';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1024*1024*1024*1024*1024-1);
$expected = '1024.00 TB';
$this->assertEquals($expected, $result);
$result = $this->Number->toReadableSize(1024*1024*1024*1024*1024*1024);
$expected = (1024 * 1024) . '.00 TB';
$this->assertEquals($expected, $result);
}
/**
* testToPercentage method
*
* @return void
*/
public function testToPercentage() {
$result = $this->Number->toPercentage(45, 0);
$expected = '45%';
$this->assertEquals($expected, $result);
$result = $this->Number->toPercentage(45, 2);
$expected = '45.00%';
$this->assertEquals($expected, $result);
$result = $this->Number->toPercentage(0, 0);
$expected = '0%';
$this->assertEquals($expected, $result);
$result = $this->Number->toPercentage(0, 4);
$expected = '0.0000%';
$this->assertEquals($expected, $result);
}
}

View file

@ -20,6 +20,14 @@
App::uses('View', 'View');
App::uses('TextHelper', 'View/Helper');
class TextHelperTestObject extends TextHelper {
public function attach(String $string) {
$this->_String = $string;
}
}
/**
* TextHelperTest class
*
@ -48,185 +56,20 @@ class TextHelperTest extends CakeTestCase {
}
/**
* testTruncate method
*
* @return void
* test String class methods are called correctly
*/
public function testTruncate() {
$text1 = 'The quick brown fox jumps over the lazy dog';
$text2 = 'Heiz&ouml;lr&uuml;cksto&szlig;abd&auml;mpfung';
$text3 = '<b>&copy; 2005-2007, Cake Software Foundation, Inc.</b><br />written by Alexander Wegener';
$text4 = '<img src="mypic.jpg"> This image tag is not XHTML conform!<br><hr/><b>But the following image tag should be conform <img src="mypic.jpg" alt="Me, myself and I" /></b><br />Great, or?';
$text5 = '0<b>1<i>2<span class="myclass">3</span>4<u>5</u>6</i>7</b>8<b>9</b>0';
$text6 = '<p><strong>Extra dates have been announced for this year\'s tour.</strong></p><p>Tickets for the new shows in</p>';
$text7 = 'El moño está en el lugar correcto. Eso fue lo que dijo la niña, ¿habrá dicho la verdad?';
$text8 = 'Vive la R' . chr(195) . chr(169) . 'publique de France';
$text9 = 'НОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыь';
$this->assertSame($this->Text->truncate($text1, 15), 'The quick br...');
$this->assertSame($this->Text->truncate($text1, 15, array('exact' => false)), 'The quick...');
$this->assertSame($this->Text->truncate($text1, 100), 'The quick brown fox jumps over the lazy dog');
$this->assertSame($this->Text->truncate($text2, 10), 'Heiz&ou...');
$this->assertSame($this->Text->truncate($text2, 10, array('exact' => false)), '...');
$this->assertSame($this->Text->truncate($text3, 20), '<b>&copy; 2005-20...');
$this->assertSame($this->Text->truncate($text4, 15), '<img src="my...');
$this->assertSame($this->Text->truncate($text5, 6, array('ending' => '')), '0<b>1<');
$this->assertSame($this->Text->truncate($text1, 15, array('html' => true)), 'The quick br...');
$this->assertSame($this->Text->truncate($text1, 15, array('exact' => false, 'html' => true)), 'The quick...');
$this->assertSame($this->Text->truncate($text2, 10, array('html' => true)), 'Heiz&ouml;lr...');
$this->assertSame($this->Text->truncate($text2, 10, array('exact' => false, 'html' => true)), '...');
$this->assertSame($this->Text->truncate($text3, 20, array('html' => true)), '<b>&copy; 2005-2007, Cake...</b>');
$this->assertSame($this->Text->truncate($text4, 15, array('html' => true)), '<img src="mypic.jpg"> This image ...');
$this->assertSame($this->Text->truncate($text4, 45, array('html' => true)), '<img src="mypic.jpg"> This image tag is not XHTML conform!<br><hr/><b>But t...</b>');
$this->assertSame($this->Text->truncate($text4, 90, array('html' => true)), '<img src="mypic.jpg"> This image tag is not XHTML conform!<br><hr/><b>But the following image tag should be conform <img src="mypic.jpg" alt="Me, myself and I" /></b><br />Grea...');
$this->assertSame($this->Text->truncate($text5, 6, array('ending' => '', 'html' => true)), '0<b>1<i>2<span class="myclass">3</span>4<u>5</u></i></b>');
$this->assertSame($this->Text->truncate($text5, 20, array('ending' => '', 'html' => true)), $text5);
$this->assertSame($this->Text->truncate($text6, 57, array('exact' => false, 'html' => true)), "<p><strong>Extra dates have been announced for this year's...</strong></p>");
$this->assertSame($this->Text->truncate($text7, 255), $text7);
$this->assertSame($this->Text->truncate($text7, 15), 'El moño está...');
$this->assertSame($this->Text->truncate($text8, 15), 'Vive la R'.chr(195).chr(169).'pu...');
$this->assertSame($this->Text->truncate($text9, 10), 'НОПРСТУ...');
$text = '<p><span style="font-size: medium;"><a>Iamatestwithnospacesandhtml</a></span></p>';
$result = $this->Text->truncate($text, 10, array(
'ending' => '...',
'exact' => false,
'html' => true
));
$expected = '<p><span style="font-size: medium;"><a>...</a></span></p>';
$this->assertEquals($expected, $result);
$text = '<p><span style="font-size: medium;">El biógrafo de Steve Jobs, Walter
Isaacson, explica porqué Jobs le pidió que le hiciera su biografía en
este artículo de El País.</span></p>
<p><span style="font-size: medium;"><span style="font-size:
large;">Por qué Steve era distinto.</span></span></p>
<p><span style="font-size: medium;"><a href="http://www.elpais.com/
articulo/primer/plano/Steve/era/distinto/elpepueconeg/
20111009elpneglse_4/Tes">http://www.elpais.com/articulo/primer/plano/
Steve/era/distinto/elpepueconeg/20111009elpneglse_4/Tes</a></span></p>
<p><span style="font-size: medium;">Ya se ha publicado la biografía de
Steve Jobs escrita por Walter Isaacson "<strong>Steve Jobs by Walter
Isaacson</strong>", aquí os dejamos la dirección de amazon donde
podeís adquirirla.</span></p>
<p><span style="font-size: medium;"><a>http://www.amazon.com/Steve-
Jobs-Walter-Isaacson/dp/1451648537</a></span></p>';
$result = $this->Text->truncate($text, 500, array(
'ending' => '... ',
'exact' => false,
'html' => true
));
$expected = '<p><span style="font-size: medium;">El biógrafo de Steve Jobs, Walter
Isaacson, explica porqué Jobs le pidió que le hiciera su biografía en
este artículo de El País.</span></p>
<p><span style="font-size: medium;"><span style="font-size:
large;">Por qué Steve era distinto.</span></span></p>
<p><span style="font-size: medium;"><a href="http://www.elpais.com/
articulo/primer/plano/Steve/era/distinto/elpepueconeg/
20111009elpneglse_4/Tes">http://www.elpais.com/articulo/primer/plano/
Steve/era/distinto/elpepueconeg/20111009elpneglse_4/Tes</a></span></p>
<p><span style="font-size: medium;">Ya se ha publicado la biografía de
Steve Jobs escrita por Walter Isaacson "<strong>Steve Jobs by Walter
Isaacson</strong>", aquí os dejamos la dirección de amazon donde
podeís adquirirla.</span></p>
<p><span style="font-size: medium;"><a>... </a></span></p>';
$this->assertEquals($expected, $result);
}
/**
* testHighlight method
*
* @return void
*/
public function testHighlight() {
$text = 'This is a test text';
$phrases = array('This', 'text');
$result = $this->Text->highlight($text, $phrases, array('format' => '<b>\1</b>'));
$expected = '<b>This</b> is a test <b>text</b>';
$this->assertEquals($expected, $result);
$text = 'This is a test text';
$phrases = null;
$result = $this->Text->highlight($text, $phrases, array('format' => '<b>\1</b>'));
$this->assertEquals($result, $text);
$text = 'This is a (test) text';
$phrases = '(test';
$result = $this->Text->highlight($text, $phrases, array('format' => '<b>\1</b>'));
$this->assertEquals('This is a <b>(test</b>) text', $result);
$text = 'Ich saß in einem Café am Übergang';
$expected = 'Ich <b>saß</b> in einem <b>Café</b> am <b>Übergang</b>';
$phrases = array('saß', 'café', 'übergang');
$result = $this->Text->highlight($text, $phrases, array('format' => '<b>\1</b>'));
$this->assertEquals($expected, $result);
}
/**
* testHighlightHtml method
*
* @return void
*/
public function testHighlightHtml() {
$text1 = '<p>strongbow isn&rsquo;t real cider</p>';
$text2 = '<p>strongbow <strong>isn&rsquo;t</strong> real cider</p>';
$text3 = '<img src="what-a-strong-mouse.png" alt="What a strong mouse!" />';
$text4 = 'What a strong mouse: <img src="what-a-strong-mouse.png" alt="What a strong mouse!" />';
$options = array('format' => '<b>\1</b>', 'html' => true);
$expected = '<p><b>strong</b>bow isn&rsquo;t real cider</p>';
$this->assertEquals($this->Text->highlight($text1, 'strong', $options), $expected);
$expected = '<p><b>strong</b>bow <strong>isn&rsquo;t</strong> real cider</p>';
$this->assertEquals($this->Text->highlight($text2, 'strong', $options), $expected);
$this->assertEquals($this->Text->highlight($text3, 'strong', $options), $text3);
$this->assertEquals($this->Text->highlight($text3, array('strong', 'what'), $options), $text3);
$expected = '<b>What</b> a <b>strong</b> mouse: <img src="what-a-strong-mouse.png" alt="What a strong mouse!" />';
$this->assertEquals($this->Text->highlight($text4, array('strong', 'what'), $options), $expected);
}
/**
* testHighlightMulti method
*
* @return void
*/
public function testHighlightMulti() {
$text = 'This is a test text';
$phrases = array('This', 'text');
$result = $this->Text->highlight($text, $phrases, array('format' => array('<b>\1</b>', '<em>\1</em>')));
$expected = '<b>This</b> is a test <em>text</em>';
$this->assertEquals($expected, $result);
}
/**
* testStripLinks method
*
* @return void
*/
public function testStripLinks() {
$text = 'This is a test text';
$expected = 'This is a test text';
$result = $this->Text->stripLinks($text);
$this->assertEquals($expected, $result);
$text = 'This is a <a href="#">test</a> text';
$expected = 'This is a test text';
$result = $this->Text->stripLinks($text);
$this->assertEquals($expected, $result);
$text = 'This <strong>is</strong> a <a href="#">test</a> <a href="#">text</a>';
$expected = 'This <strong>is</strong> a test text';
$result = $this->Text->stripLinks($text);
$this->assertEquals($expected, $result);
$text = 'This <strong>is</strong> a <a href="#">test</a> and <abbr>some</abbr> other <a href="#">text</a>';
$expected = 'This <strong>is</strong> a test and <abbr>some</abbr> other text';
$result = $this->Text->stripLinks($text);
$this->assertEquals($expected, $result);
public function testTextHelperProxyMethodCalls() {
$this->String = $this->getMock('String');
unset($this->Text);
$this->Text = new TextHelperTestObject($this->View);
$this->Text->attach($this->String);
$methods = array(
'highlight', 'stripLinks', 'truncate', 'excerpt', 'toList',
);
foreach ($methods as $method) {
$this->String->expects($this->at(0))->method($method);
$this->Text->{$method}('who', 'what', 'when', 'where', 'how');
}
}
/**
@ -405,107 +248,4 @@ podeís adquirirla.</span></p>
$this->assertEquals($expected, $result);
}
/**
* testHighlightCaseInsensitivity method
*
* @return void
*/
public function testHighlightCaseInsensitivity() {
$text = 'This is a Test text';
$expected = 'This is a <b>Test</b> text';
$result = $this->Text->highlight($text, 'test', array('format' => '<b>\1</b>'));
$this->assertEquals($expected, $result);
$result = $this->Text->highlight($text, array('test'), array('format' => '<b>\1</b>'));
$this->assertEquals($expected, $result);
}
/**
* testExcerpt method
*
* @return void
*/
public function testExcerpt() {
$text = 'This is a phrase with test text to play with';
$expected = '...ase with test text to ...';
$result = $this->Text->excerpt($text, 'test', 9, '...');
$this->assertEquals($expected, $result);
$expected = 'This is a...';
$result = $this->Text->excerpt($text, 'not_found', 9, '...');
$this->assertEquals($expected, $result);
$expected = 'This is a phras...';
$result = $this->Text->excerpt($text, null, 9, '...');
$this->assertEquals($expected, $result);
$expected = $text;
$result = $this->Text->excerpt($text, null, 200, '...');
$this->assertEquals($expected, $result);
$expected = '...a phrase w...';
$result = $this->Text->excerpt($text, 'phrase', 2, '...');
$this->assertEquals($expected, $result);
$phrase = 'This is a phrase with test text';
$expected = $text;
$result = $this->Text->excerpt($text, $phrase, 13, '...');
$this->assertEquals($expected, $result);
$text = 'aaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaa';
$phrase = 'bbbbbbbb';
$result = $this->Text->excerpt($text, $phrase, 10);
$expected = '...aaaaaaaaaabbbbbbbbaaaaaaaaaa...';
$this->assertEquals($expected, $result);
}
/**
* testExcerptCaseInsensitivity method
*
* @return void
*/
public function testExcerptCaseInsensitivity() {
$text = 'This is a phrase with test text to play with';
$expected = '...ase with test text to ...';
$result = $this->Text->excerpt($text, 'TEST', 9, '...');
$this->assertEquals($expected, $result);
$expected = 'This is a...';
$result = $this->Text->excerpt($text, 'NOT_FOUND', 9, '...');
$this->assertEquals($expected, $result);
}
/**
* testListGeneration method
*
* @return void
*/
public function testListGeneration() {
$result = $this->Text->toList(array());
$this->assertEquals($result, '');
$result = $this->Text->toList(array('One'));
$this->assertEquals($result, 'One');
$result = $this->Text->toList(array('Larry', 'Curly', 'Moe'));
$this->assertEquals($result, 'Larry, Curly and Moe');
$result = $this->Text->toList(array('Dusty', 'Lucky', 'Ned'), 'y');
$this->assertEquals($result, 'Dusty, Lucky y Ned');
$result = $this->Text->toList(array(1 => 'Dusty', 2 => 'Lucky', 3 => 'Ned'), 'y');
$this->assertEquals($result, 'Dusty, Lucky y Ned');
$result = $this->Text->toList(array(1 => 'Dusty', 2 => 'Lucky', 3 => 'Ned'), 'and', ' + ');
$this->assertEquals($result, 'Dusty + Lucky and Ned');
$result = $this->Text->toList(array('name1' => 'Dusty', 'name2' => 'Lucky'));
$this->assertEquals($result, 'Dusty and Lucky');
$result = $this->Text->toList(array('test_0' => 'banana', 'test_1' => 'apple', 'test_2' => 'lemon'));
$this->assertEquals($result, 'banana, apple and lemon');
}
}

View file

@ -18,6 +18,18 @@
*/
App::uses('TimeHelper', 'View/Helper');
App::uses('View', 'View');
App::uses('CakeTime', 'Utility');
/**
* TimeHelperTestObject class
*/
class TimeHelperTestObject extends TimeHelper {
public function attach(CakeTime $cakeTime) {
$this->_CakeTime = $cakeTime;
}
}
/**
* TimeHelperTest class
@ -26,15 +38,20 @@ App::uses('View', 'View');
*/
class TimeHelperTest extends CakeTestCase {
public $Time = null;
public $CakeTime = null;
/**
* setUp method
*
* @return void
*/
public function setUp() {
$controller = null;
$View = new View($controller);
$this->Time = new TimeHelper($View);
$View = new View(null);
$this->CakeTime = $this->getMock('CakeTime');
$this->Time = new TimeHelperTestObject($View);
$this->Time->attach($this->CakeTime);
}
/**
@ -44,767 +61,24 @@ class TimeHelperTest extends CakeTestCase {
*/
public function tearDown() {
unset($this->Time);
unset($this->CakeTime);
}
/**
* testToQuarter method
*
* @return void
* test CakeTime class methods are called correctly
*/
public function testToQuarter() {
$result = $this->Time->toQuarter('2007-12-25');
$this->assertEquals($result, 4);
$result = $this->Time->toQuarter('2007-9-25');
$this->assertEquals($result, 3);
$result = $this->Time->toQuarter('2007-3-25');
$this->assertEquals($result, 1);
$result = $this->Time->toQuarter('2007-3-25', true);
$this->assertEquals($result, array('2007-01-01', '2007-03-31'));
$result = $this->Time->toQuarter('2007-5-25', true);
$this->assertEquals($result, array('2007-04-01', '2007-06-30'));
$result = $this->Time->toQuarter('2007-8-25', true);
$this->assertEquals($result, array('2007-07-01', '2007-09-30'));
$result = $this->Time->toQuarter('2007-12-25', true);
$this->assertEquals($result, array('2007-10-01', '2007-12-31'));
}
/**
* testTimeAgoInWords method
*
* @return void
*/
public function testTimeAgoInWords() {
$result = $this->Time->timeAgoInWords('-1 week');
$this->assertEquals($result, '1 week ago');
$result = $this->Time->timeAgoInWords('+1 week');
$this->assertEquals($result, '1 week');
$result = $this->Time->timeAgoInWords(strtotime('+4 months +2 weeks +3 days'), array('end' => '8 years'), true);
$this->assertEquals($result, '4 months, 2 weeks, 3 days');
$result = $this->Time->timeAgoInWords(strtotime('+4 months +2 weeks +2 days'), array('end' => '8 years'), true);
$this->assertEquals($result, '4 months, 2 weeks, 2 days');
$result = $this->Time->timeAgoInWords(strtotime('+4 months +2 weeks +1 day'), array('end' => '8 years'), true);
$this->assertEquals($result, '4 months, 2 weeks, 1 day');
$result = $this->Time->timeAgoInWords(strtotime('+3 months +2 weeks +1 day'), array('end' => '8 years'), true);
$this->assertEquals($result, '3 months, 2 weeks, 1 day');
$result = $this->Time->timeAgoInWords(strtotime('+3 months +2 weeks'), array('end' => '8 years'), true);
$this->assertEquals($result, '3 months, 2 weeks');
$result = $this->Time->timeAgoInWords(strtotime('+3 months +1 week +6 days'), array('end' => '8 years'), true);
$this->assertEquals($result, '3 months, 1 week, 6 days');
$result = $this->Time->timeAgoInWords(strtotime('+2 months +2 weeks +1 day'), array('end' => '8 years'), true);
$this->assertEquals($result, '2 months, 2 weeks, 1 day');
$result = $this->Time->timeAgoInWords(strtotime('+2 months +2 weeks'), array('end' => '8 years'), true);
$this->assertEquals($result, '2 months, 2 weeks');
$result = $this->Time->timeAgoInWords(strtotime('+2 months +1 week +6 days'), array('end' => '8 years'), true);
$this->assertEquals($result, '2 months, 1 week, 6 days');
$result = $this->Time->timeAgoInWords(strtotime('+1 month +1 week +6 days'), array('end' => '8 years'), true);
$this->assertEquals($result, '1 month, 1 week, 6 days');
for ($i = 0; $i < 200; $i ++) {
$years = mt_rand(0, 3);
$months = mt_rand(0, 11);
$weeks = mt_rand(0, 3);
$days = mt_rand(0, 6);
$hours = 0;
$minutes = 0;
$seconds = 0;
$relative_date = '';
// Trying to take into account the number of days in a month
$month = date('m') - $months;
if ($month <= 0) {
$month = $months % 12;
}
$time = mktime(0, 0, 0, $month, 1, date('y') - $years);
$diffDays = date('t') - date('t', $time);
if ($diffDays > 0 && date('j') - date('t', $time) - $days > 0 && $months > 0 && $weeks === 0) {
continue;
}
if ($years > 0) {
// years and months and days
$relative_date .= ($relative_date ? ', -' : '-') . $years . ' year' . ($years > 1 ? 's' : '');
$relative_date .= $months > 0 ? ($relative_date ? ', -' : '-') . $months . ' month' . ($months > 1 ? 's' : '') : '';
$relative_date .= $weeks > 0 ? ($relative_date ? ', -' : '-') . $weeks . ' week' . ($weeks > 1 ? 's' : '') : '';
$relative_date .= $days > 0 ? ($relative_date ? ', -' : '-') . $days . ' day' . ($days > 1 ? 's' : '') : '';
} elseif (abs($months) > 0) {
// months, weeks and days
$relative_date .= ($relative_date ? ', -' : '-') . $months . ' month' . ($months > 1 ? 's' : '');
$relative_date .= $weeks > 0 ? ($relative_date ? ', -' : '-') . $weeks . ' week' . ($weeks > 1 ? 's' : '') : '';
$relative_date .= $days > 0 ? ($relative_date ? ', -' : '-') . $days . ' day' . ($days > 1 ? 's' : '') : '';
} elseif (abs($weeks) > 0) {
// weeks and days
$relative_date .= ($relative_date ? ', -' : '-') . $weeks . ' week' . ($weeks > 1 ? 's' : '');
$relative_date .= $days > 0 ? ($relative_date ? ', -' : '-') . $days . ' day' . ($days > 1 ? 's' : '') : '';
} elseif (abs($days) > 0) {
// days and hours
$relative_date .= ($relative_date ? ', -' : '-') . $days . ' day' . ($days > 1 ? 's' : '');
$relative_date .= $hours > 0 ? ($relative_date ? ', -' : '-') . $hours . ' hour' . ($hours > 1 ? 's' : '') : '';
} elseif (abs($hours) > 0) {
// hours and minutes
$relative_date .= ($relative_date ? ', -' : '-') . $hours . ' hour' . ($hours > 1 ? 's' : '');
$relative_date .= $minutes > 0 ? ($relative_date ? ', -' : '-') . $minutes . ' minute' . ($minutes > 1 ? 's' : '') : '';
} elseif (abs($minutes) > 0) {
// minutes only
$relative_date .= ($relative_date ? ', -' : '-') . $minutes . ' minute' . ($minutes > 1 ? 's' : '');
} else {
// seconds only
$relative_date .= ($relative_date ? ', -' : '-') . $seconds . ' second' . ($seconds != 1 ? 's' : '');
}
if (date('j/n/y', strtotime(str_replace(',', '', $relative_date))) != '1/1/70') {
$result = $this->Time->timeAgoInWords(strtotime(str_replace(',', '', $relative_date)), array('end' => '8 years'), true);
if ($relative_date == '0 seconds') {
$relative_date = '0 seconds ago';
}
$relative_date = str_replace('-', '', $relative_date) . ' ago';
$this->assertEquals($result, $relative_date);
}
}
for ($i = 0; $i < 200; $i ++) {
$years = mt_rand(0, 3);
$months = mt_rand(0, 11);
$weeks = mt_rand(0, 3);
$days = mt_rand(0, 6);
$hours = 0;
$minutes = 0;
$seconds = 0;
$relative_date = '';
if ($years > 0) {
// years and months and days
$relative_date .= ($relative_date ? ', ' : '') . $years . ' year' . ($years > 1 ? 's' : '');
$relative_date .= $months > 0 ? ($relative_date ? ', ' : '') . $months . ' month' . ($months > 1 ? 's' : '') : '';
$relative_date .= $weeks > 0 ? ($relative_date ? ', ' : '') . $weeks . ' week' . ($weeks > 1 ? 's' : '') : '';
$relative_date .= $days > 0 ? ($relative_date ? ', ' : '') . $days . ' day' . ($days > 1 ? 's' : '') : '';
} elseif (abs($months) > 0) {
// months, weeks and days
$relative_date .= ($relative_date ? ', ' : '') . $months . ' month' . ($months > 1 ? 's' : '');
$relative_date .= $weeks > 0 ? ($relative_date ? ', ' : '') . $weeks . ' week' . ($weeks > 1 ? 's' : '') : '';
$relative_date .= $days > 0 ? ($relative_date ? ', ' : '') . $days . ' day' . ($days > 1 ? 's' : '') : '';
} elseif (abs($weeks) > 0) {
// weeks and days
$relative_date .= ($relative_date ? ', ' : '') . $weeks . ' week' . ($weeks > 1 ? 's' : '');
$relative_date .= $days > 0 ? ($relative_date ? ', ' : '') . $days . ' day' . ($days > 1 ? 's' : '') : '';
} elseif (abs($days) > 0) {
// days and hours
$relative_date .= ($relative_date ? ', ' : '') . $days . ' day' . ($days > 1 ? 's' : '');
$relative_date .= $hours > 0 ? ($relative_date ? ', ' : '') . $hours . ' hour' . ($hours > 1 ? 's' : '') : '';
} elseif (abs($hours) > 0) {
// hours and minutes
$relative_date .= ($relative_date ? ', ' : '') . $hours . ' hour' . ($hours > 1 ? 's' : '');
$relative_date .= $minutes > 0 ? ($relative_date ? ', ' : '') . $minutes . ' minute' . ($minutes > 1 ? 's' : '') : '';
} elseif (abs($minutes) > 0) {
// minutes only
$relative_date .= ($relative_date ? ', ' : '') . $minutes . ' minute' . ($minutes > 1 ? 's' : '');
} else {
// seconds only
$relative_date .= ($relative_date ? ', ' : '') . $seconds . ' second' . ($seconds != 1 ? 's' : '');
}
if (date('j/n/y', strtotime(str_replace(',', '', $relative_date))) != '1/1/70') {
$result = $this->Time->timeAgoInWords(strtotime(str_replace(',', '', $relative_date)), array('end' => '8 years'), true);
if ($relative_date == '0 seconds') {
$relative_date = '0 seconds ago';
}
$relative_date = str_replace('-', '', $relative_date) . '';
$this->assertEquals($result, $relative_date);
}
}
$result = $this->Time->timeAgoInWords(strtotime('-2 years -5 months -2 days'), array('end' => '3 years'), true);
$this->assertEquals($result, '2 years, 5 months, 2 days ago');
$result = $this->Time->timeAgoInWords('2007-9-25');
$this->assertEquals($result, 'on 25/9/07');
$result = $this->Time->timeAgoInWords('2007-9-25', 'Y-m-d');
$this->assertEquals($result, 'on 2007-09-25');
$result = $this->Time->timeAgoInWords('2007-9-25', 'Y-m-d', true);
$this->assertEquals($result, 'on 2007-09-25');
$result = $this->Time->timeAgoInWords(strtotime('-2 weeks -2 days'), 'Y-m-d', false);
$this->assertEquals($result, '2 weeks, 2 days ago');
$result = $this->Time->timeAgoInWords(strtotime('+2 weeks +2 days'), 'Y-m-d', true);
$this->assertRegExp('/^2 weeks, [1|2] day(s)?$/', $result);
$result = $this->Time->timeAgoInWords(strtotime('+2 months +2 days'), array('end' => '1 month'));
$this->assertEquals($result, 'on ' . date('j/n/y', strtotime('+2 months +2 days')));
$result = $this->Time->timeAgoInWords(strtotime('+2 months +2 days'), array('end' => '3 month'));
$this->assertRegExp('/2 months/', $result);
$result = $this->Time->timeAgoInWords(strtotime('+2 months +12 days'), array('end' => '3 month'));
$this->assertRegExp('/2 months, 1 week/', $result);
$result = $this->Time->timeAgoInWords(strtotime('+3 months +5 days'), array('end' => '4 month'));
$this->assertEquals($result, '3 months, 5 days');
$result = $this->Time->timeAgoInWords(strtotime('-2 months -2 days'), array('end' => '3 month'));
$this->assertEquals($result, '2 months, 2 days ago');
$result = $this->Time->timeAgoInWords(strtotime('-2 months -2 days'), array('end' => '3 month'));
$this->assertEquals($result, '2 months, 2 days ago');
$result = $this->Time->timeAgoInWords(strtotime('+2 months +2 days'), array('end' => '3 month'));
$this->assertRegExp('/2 months/', $result);
$result = $this->Time->timeAgoInWords(strtotime('+2 months +2 days'), array('end' => '1 month', 'format' => 'Y-m-d'));
$this->assertEquals($result, 'on ' . date('Y-m-d', strtotime('+2 months +2 days')));
$result = $this->Time->timeAgoInWords(strtotime('-2 months -2 days'), array('end' => '1 month', 'format' => 'Y-m-d'));
$this->assertEquals($result, 'on ' . date('Y-m-d', strtotime('-2 months -2 days')));
$result = $this->Time->timeAgoInWords(strtotime('-13 months -5 days'), array('end' => '2 years'));
$this->assertEquals($result, '1 year, 1 month, 5 days ago');
$fourHours = $this->Time->timeAgoInWords(strtotime('-5 days -2 hours'), array('userOffset' => -4));
$result = $this->Time->timeAgoInWords(strtotime('-5 days -2 hours'), array('userOffset' => 4));
$this->assertEquals($fourHours, $result);
$result = $this->Time->timeAgoInWords(strtotime('-2 hours'));
$expected = '2 hours ago';
$this->assertEquals($expected, $result);
$result = $this->Time->timeAgoInWords(strtotime('-12 minutes'));
$expected = '12 minutes ago';
$this->assertEquals($expected, $result);
$result = $this->Time->timeAgoInWords(strtotime('-12 seconds'));
$expected = '12 seconds ago';
$this->assertEquals($expected, $result);
$time = strtotime('-3 years -12 months');
$result = $this->Time->timeAgoInWords($time);
$expected = 'on ' . date('j/n/y', $time);
$this->assertEquals($expected, $result);
}
/**
* testNice method
*
* @return void
*/
public function testNice() {
$time = time() + 2 * DAY;
$this->assertEquals(date('D, M jS Y, H:i', $time), $this->Time->nice($time));
$time = time() - 2 * DAY;
$this->assertEquals(date('D, M jS Y, H:i', $time), $this->Time->nice($time));
$time = time();
$this->assertEquals(date('D, M jS Y, H:i', $time), $this->Time->nice($time));
$time = 0;
$this->assertEquals(date('D, M jS Y, H:i', time()), $this->Time->nice($time));
$time = null;
$this->assertEquals(date('D, M jS Y, H:i', time()), $this->Time->nice($time));
$time = time();
$this->assertEquals(date('D', $time), $this->Time->nice($time, null, '%a'));
$this->assertEquals(date('M d, Y', $time), $this->Time->nice($time, null, '%b %d, %Y'));
$this->Time->niceFormat = '%Y-%d-%m';
$this->assertEquals(date('Y-d-m', $time), $this->Time->nice($time));
}
/**
* testNiceShort method
*
* @return void
*/
public function testNiceShort() {
$time = time() + 2 * DAY;
if (date('Y', $time) == date('Y')) {
$this->assertEquals(date('M jS, H:i', $time), $this->Time->niceShort($time));
} else {
$this->assertEquals(date('M jS Y, H:i', $time), $this->Time->niceShort($time));
}
$time = time();
$this->assertEquals('Today, ' . date('H:i', $time), $this->Time->niceShort($time));
$time = time() - DAY;
$this->assertEquals('Yesterday, ' . date('H:i', $time), $this->Time->niceShort($time));
}
/**
* testDaysAsSql method
*
* @return void
*/
public function testDaysAsSql() {
$begin = time();
$end = time() + DAY;
$field = 'my_field';
$expected = '(my_field >= \''.date('Y-m-d', $begin).' 00:00:00\') AND (my_field <= \''.date('Y-m-d', $end).' 23:59:59\')';
$this->assertEquals($expected, $this->Time->daysAsSql($begin, $end, $field));
}
/**
* testDayAsSql method
*
* @return void
*/
public function testDayAsSql() {
$time = time();
$field = 'my_field';
$expected = '(my_field >= \''.date('Y-m-d', $time).' 00:00:00\') AND (my_field <= \''.date('Y-m-d', $time).' 23:59:59\')';
$this->assertEquals($expected, $this->Time->dayAsSql($time, $field));
}
/**
* testToUnix method
*
* @return void
*/
public function testToUnix() {
$this->assertEquals(time(), $this->Time->toUnix(time()));
$this->assertEquals(strtotime('+1 day'), $this->Time->toUnix('+1 day'));
$this->assertEquals(strtotime('+0 days'), $this->Time->toUnix('+0 days'));
$this->assertEquals(strtotime('-1 days'), $this->Time->toUnix('-1 days'));
$this->assertEquals(false, $this->Time->toUnix(''));
$this->assertEquals(false, $this->Time->toUnix(null));
}
/**
* testToAtom method
*
* @return void
*/
public function testToAtom() {
$this->assertEquals(date('Y-m-d\TH:i:s\Z'), $this->Time->toAtom(time()));
}
/**
* testToRss method
*
* @return void
*/
public function testToRss() {
$this->assertEquals(date('r'), $this->Time->toRss(time()));
if (!$this->skipIf(!class_exists('DateTimeZone'), '%s DateTimeZone class not available.')) {
$timezones = array('Europe/London', 'Europe/Brussels', 'UTC', 'America/Denver', 'America/Caracas', 'Asia/Kathmandu');
foreach ($timezones as $timezone) {
$yourTimezone = new DateTimeZone($timezone);
$yourTime = new DateTime('now', $yourTimezone);
$userOffset = $yourTimezone->getOffset($yourTime) / HOUR;
$this->assertEquals($yourTime->format('r'), $this->Time->toRss(time(), $userOffset));
}
public function testTimeHelperProxyMethodCalls() {
$methods = array(
'convertSpecifiers', 'convert', 'serverOffset', 'fromString',
'nice', 'niceShort', 'daysAsSql', 'dayAsSql',
'isToday', 'isThisMonth', 'isThisYear', 'wasYesterday',
'isTomorrow', 'toQuarter', 'toUnix', 'toAtom', 'toRSS',
'timeAgoInWords', 'wasWithinLast', 'gmt', 'format', 'i18nFormat',
);
foreach ($methods as $method) {
$this->CakeTime->expects($this->at(0))->method($method);
$this->Time->{$method}('who', 'what', 'when', 'where', 'how');
}
}
/**
* testFormat method
*
* @return void
*/
public function testFormat() {
$format = 'D-M-Y';
$arr = array(time(), strtotime('+1 days'), strtotime('+1 days'), strtotime('+0 days'));
foreach ($arr as $val) {
$this->assertEquals(date($format, $val), $this->Time->format($format, $val));
}
$result = $this->Time->format('Y-m-d', null, 'never');
$this->assertEquals($result, 'never');
}
/**
* testOfGmt method
*
* @return void
*/
public function testGmt() {
$hour = 3;
$min = 4;
$sec = 2;
$month = 5;
$day = 14;
$year = 2007;
$time = mktime($hour, $min, $sec, $month, $day, $year);
$expected = gmmktime($hour, $min, $sec, $month, $day, $year);
$this->assertEquals($expected, $this->Time->gmt(date('Y-n-j G:i:s', $time)));
$hour = date('H');
$min = date('i');
$sec = date('s');
$month = date('m');
$day = date('d');
$year = date('Y');
$expected = gmmktime($hour, $min, $sec, $month, $day, $year);
$this->assertEquals($expected, $this->Time->gmt(null));
}
/**
* testIsToday method
*
* @return void
*/
public function testIsToday() {
$result = $this->Time->isToday('+1 day');
$this->assertFalse($result);
$result = $this->Time->isToday('+1 days');
$this->assertFalse($result);
$result = $this->Time->isToday('+0 day');
$this->assertTrue($result);
$result = $this->Time->isToday('-1 day');
$this->assertFalse($result);
}
/**
* testIsThisWeek method
*
* @return void
*/
public function testIsThisWeek() {
// A map of days which goes from -1 day of week to +1 day of week
$map = array(
'Mon' => array(-1, 7), 'Tue' => array(-2, 6), 'Wed' => array(-3, 5),
'Thu' => array(-4, 4), 'Fri' => array(-5, 3), 'Sat' => array(-6, 2),
'Sun' => array(-7, 1)
);
$days = $map[date('D')];
for ($day = $days[0] + 1; $day < $days[1]; $day++) {
$this->assertTrue($this->Time->isThisWeek(($day > 0 ? '+' : '') . $day . ' days'));
}
$this->assertFalse($this->Time->isThisWeek($days[0] . ' days'));
$this->assertFalse($this->Time->isThisWeek('+' . $days[1] . ' days'));
}
/**
* testIsThisMonth method
*
* @return void
*/
public function testIsThisMonth() {
$result = $this->Time->isThisMonth('+0 day');
$this->assertTrue($result);
$result = $this->Time->isThisMonth($time = mktime(0, 0, 0, date('m'), mt_rand(1, 28), date('Y')));
$this->assertTrue($result);
$result = $this->Time->isThisMonth(mktime(0, 0, 0, date('m'), mt_rand(1, 28), date('Y') - mt_rand(1, 12)));
$this->assertFalse($result);
$result = $this->Time->isThisMonth(mktime(0, 0, 0, date('m'), mt_rand(1, 28), date('Y') + mt_rand(1, 12)));
$this->assertFalse($result);
}
/**
* testIsThisYear method
*
* @return void
*/
public function testIsThisYear() {
$result = $this->Time->isThisYear('+0 day');
$this->assertTrue($result);
$result = $this->Time->isThisYear(mktime(0, 0, 0, mt_rand(1, 12), mt_rand(1, 28), date('Y')));
$this->assertTrue($result);
}
/**
* testWasYesterday method
*
* @return void
*/
public function testWasYesterday() {
$result = $this->Time->wasYesterday('+1 day');
$this->assertFalse($result);
$result = $this->Time->wasYesterday('+1 days');
$this->assertFalse($result);
$result = $this->Time->wasYesterday('+0 day');
$this->assertFalse($result);
$result = $this->Time->wasYesterday('-1 day');
$this->assertTrue($result);
$result = $this->Time->wasYesterday('-1 days');
$this->assertTrue($result);
$result = $this->Time->wasYesterday('-2 days');
$this->assertFalse($result);
}
/**
* testIsTomorrow method
*
* @return void
*/
public function testIsTomorrow() {
$result = $this->Time->isTomorrow('+1 day');
$this->assertTrue($result);
$result = $this->Time->isTomorrow('+1 days');
$this->assertTrue($result);
$result = $this->Time->isTomorrow('+0 day');
$this->assertFalse($result);
$result = $this->Time->isTomorrow('-1 day');
$this->assertFalse($result);
}
/**
* testWasWithinLast method
*
* @return void
*/
public function testWasWithinLast() {
$this->assertTrue($this->Time->wasWithinLast('1 day', '-1 day'));
$this->assertTrue($this->Time->wasWithinLast('1 week', '-1 week'));
$this->assertTrue($this->Time->wasWithinLast('1 year', '-1 year'));
$this->assertTrue($this->Time->wasWithinLast('1 second', '-1 second'));
$this->assertTrue($this->Time->wasWithinLast('1 minute', '-1 minute'));
$this->assertTrue($this->Time->wasWithinLast('1 year', '-1 year'));
$this->assertTrue($this->Time->wasWithinLast('1 month', '-1 month'));
$this->assertTrue($this->Time->wasWithinLast('1 day', '-1 day'));
$this->assertTrue($this->Time->wasWithinLast('1 week', '-1 day'));
$this->assertTrue($this->Time->wasWithinLast('2 week', '-1 week'));
$this->assertFalse($this->Time->wasWithinLast('1 second', '-1 year'));
$this->assertTrue($this->Time->wasWithinLast('10 minutes', '-1 second'));
$this->assertTrue($this->Time->wasWithinLast('23 minutes', '-1 minute'));
$this->assertFalse($this->Time->wasWithinLast('0 year', '-1 year'));
$this->assertTrue($this->Time->wasWithinLast('13 month', '-1 month'));
$this->assertTrue($this->Time->wasWithinLast('2 days', '-1 day'));
$this->assertFalse($this->Time->wasWithinLast('1 week', '-2 weeks'));
$this->assertFalse($this->Time->wasWithinLast('1 second', '-2 seconds'));
$this->assertFalse($this->Time->wasWithinLast('1 day', '-2 days'));
$this->assertFalse($this->Time->wasWithinLast('1 hour', '-2 hours'));
$this->assertFalse($this->Time->wasWithinLast('1 month', '-2 months'));
$this->assertFalse($this->Time->wasWithinLast('1 year', '-2 years'));
$this->assertFalse($this->Time->wasWithinLast('1 day', '-2 weeks'));
$this->assertFalse($this->Time->wasWithinLast('1 day', '-2 days'));
$this->assertFalse($this->Time->wasWithinLast('0 days', '-2 days'));
$this->assertTrue($this->Time->wasWithinLast('1 hour', '-20 seconds'));
$this->assertTrue($this->Time->wasWithinLast('1 year', '-60 minutes -30 seconds'));
$this->assertTrue($this->Time->wasWithinLast('3 years', '-2 months'));
$this->assertTrue($this->Time->wasWithinLast('5 months', '-4 months'));
$this->assertTrue($this->Time->wasWithinLast('5 ', '-3 days'));
$this->assertTrue($this->Time->wasWithinLast('1 ', '-1 hour'));
$this->assertTrue($this->Time->wasWithinLast('1 ', '-1 minute'));
$this->assertTrue($this->Time->wasWithinLast('1 ', '-23 hours -59 minutes -59 seconds'));
}
/**
* testUserOffset method
*
* @return void
*/
public function testUserOffset() {
$timezoneServer = new DateTimeZone(date_default_timezone_get());
$timeServer = new DateTime('now', $timezoneServer);
$yourTimezone = $timezoneServer->getOffset($timeServer) / HOUR;
$expected = time();
$result = $this->Time->fromString(time(), $yourTimezone);
$this->assertEquals($expected, $result);
}
/**
* test fromString()
*
* @return void
*/
public function testFromString() {
$result = $this->Time->fromString('');
$this->assertFalse($result);
$result = $this->Time->fromString(0, 0);
$this->assertFalse($result);
$result = $this->Time->fromString('+1 hour');
$expected = strtotime('+1 hour');
$this->assertEquals($expected, $result);
$timezone = date('Z', time());
$result = $this->Time->fromString('+1 hour', $timezone);
$expected = $this->Time->convert(strtotime('+1 hour'), $timezone);
$this->assertEquals($expected, $result);
}
/**
* test converting time specifiers using a time definition localfe file
*
* @return void
*/
public function testConvertSpecifiers() {
App::build(array(
'locales' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Locale' . DS)
), true);
Configure::write('Config.language', 'time_test');
$time = strtotime('Thu Jan 14 11:43:39 2010');
$result = $this->Time->convertSpecifiers('%a', $time);
$expected = 'jue';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%A', $time);
$expected = 'jueves';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%c', $time);
$expected = 'jue %d ene %Y %H:%M:%S %Z';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%C', $time);
$expected = '20';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%D', $time);
$expected = '%m/%d/%y';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%b', $time);
$expected = 'ene';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%h', $time);
$expected = 'ene';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%B', $time);
$expected = 'enero';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%n', $time);
$expected = "\n";
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%n', $time);
$expected = "\n";
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%p', $time);
$expected = 'AM';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%P', $time);
$expected = 'am';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%r', $time);
$expected = '%I:%M:%S AM';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%R', $time);
$expected = '11:43';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%t', $time);
$expected = "\t";
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%T', $time);
$expected = '%H:%M:%S';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%u', $time);
$expected = 4;
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%x', $time);
$expected = '%d/%m/%y';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%X', $time);
$expected = '%H:%M:%S';
$this->assertEquals($expected, $result);
}
/**
* test convert %e on windows.
*
* @return void
*/
public function testConvertPercentE() {
$this->skipIf(DIRECTORY_SEPARATOR !== '\\', 'Cannot run windows tests on non-windows OS.');
$time = strtotime('Thu Jan 14 11:43:39 2010');
$result = $this->Time->convertSpecifiers('%e', $time);
$expected = '14';
$this->assertEquals($expected, $result);
$result = $this->Time->convertSpecifiers('%e', strtotime('2011-01-01'));
$expected = ' 1';
$this->assertEquals($expected, $result);
}
/**
* test formatting dates taking in account preferred i18n locale file
*
* @return void
*/
public function testI18nFormat() {
App::build(array(
'locales' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Locale' . DS)
), true);
Configure::write('Config.language', 'time_test');
$time = strtotime('Thu Jan 14 13:59:28 2010');
$result = $this->Time->i18nFormat($time);
$expected = '14/01/10';
$this->assertEquals($expected, $result);
$result = $this->Time->i18nFormat($time, '%c');
$expected = 'jue 14 ene 2010 13:59:28 ' . strftime('%Z', $time);
$this->assertEquals($expected, $result);
$result = $this->Time->i18nFormat($time, 'Time is %r, and date is %x');
$expected = 'Time is 01:59:28 PM, and date is 14/01/10';
$this->assertEquals($expected, $result);
$time = strtotime('Wed Jan 13 13:59:28 2010');
$result = $this->Time->i18nFormat($time);
$expected = '13/01/10';
$this->assertEquals($expected, $result);
$result = $this->Time->i18nFormat($time, '%c');
$expected = 'mié 13 ene 2010 13:59:28 ' . strftime('%Z', $time);
$this->assertEquals($expected, $result);
$result = $this->Time->i18nFormat($time, 'Time is %r, and date is %x');
$expected = 'Time is 01:59:28 PM, and date is 13/01/10';
$this->assertEquals($expected, $result);
$result = $this->Time->i18nFormat('invalid date', '%x', 'Date invalid');
$expected = 'Date invalid';
$this->assertEquals($expected, $result);
}
/**
* test new format() syntax which inverts first and secod parameters
*
* @return void
*/
public function testFormatNewSyntax() {
$time = time();
$this->assertEquals($this->Time->format($time), $this->Time->i18nFormat($time));
$this->assertEquals($this->Time->format($time, '%c'), $this->Time->i18nFormat($time, '%c'));
}
}

View file

@ -244,6 +244,7 @@ class MediaViewTest extends CakeTestCase {
'path' => CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS,
'id' => 'no_section.ini',
'extension' => 'ini',
'name' => 'config'
);
$this->MediaView->expects($this->exactly(2))
->method('_isActive')
@ -270,7 +271,7 @@ class MediaViewTest extends CakeTestCase {
$this->MediaView->response->expects($this->once())
->method('download')
->with('no_section.ini');
->with('config.ini');
$this->MediaView->response->expects($this->at(4))
->method('header')
@ -357,7 +358,7 @@ class MediaViewTest extends CakeTestCase {
*
* @return void
*/
function testRenderUpperExtesnion() {
public function testRenderUpperExtension() {
$this->MediaView->viewVars = array(
'path' => CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS .'img' . DS,
'id' => 'test_2.JPG',
@ -376,4 +377,27 @@ class MediaViewTest extends CakeTestCase {
$this->MediaView->render();
}
/**
* Test downloading files with extension not explicitly set.
*
* @return void
*/
public function testRenderExtensionNotSet() {
$this->MediaView->viewVars = array(
'path' => CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS .'img' . DS,
'id' => 'test_2.JPG',
);
$this->MediaView->response->expects($this->any())
->method('type')
->with('jpg')
->will($this->returnArgument(0));
$this->MediaView->expects($this->at(0))
->method('_isActive')
->will($this->returnValue(true));
$this->MediaView->render();
}
}

View file

@ -726,7 +726,7 @@ class ViewTest extends CakeTestCase {
'path' => CACHE . 'views' . DS,
'prefix' => ''
));
Cache::clear('test_view');
Cache::clear(false, 'test_view');
$View = new TestView($this->PostsController);
$View->elementCache = 'test_view';
@ -763,6 +763,7 @@ class ViewTest extends CakeTestCase {
$result = Cache::read('element__test_element_cache_param_foo', 'test_view');
$this->assertEquals($expected, $result);
Cache::clear(false, 'test_view');
Cache::drop('test_view');
}

View file

@ -38,8 +38,8 @@ class UserFixture extends CakeTestFixture {
*/
public $fields = array(
'id' => array('type' => 'integer', 'key' => 'primary'),
'user' => array('type' => 'string', 'null' => false),
'password' => array('type' => 'string', 'null' => false),
'user' => array('type' => 'string', 'null' => true),
'password' => array('type' => 'string', 'null' => true),
'created' => 'datetime',
'updated' => 'datetime'
);

View file

@ -12,6 +12,7 @@ echo __dn('domain', 'You deleted %d message (domain).', 'You deleted %d messages
// Duplicated Message
echo __('Editing this Page');
echo __('You have %d new message.');
// Multiline
__('Hot features!'

View file

@ -0,0 +1,254 @@
<?php
/**
* CakeNumber Utility.
*
* Methods to make numbers more readable.
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* 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://cakephp.org CakePHP(tm) Project
* @package Cake.Utility
* @since CakePHP(tm) v 0.10.0.1076
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
/**
* Number helper library.
*
* Methods to make numbers more readable.
*
* @package Cake.Utility
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html
*/
class CakeNumber {
/**
* Currencies supported by the helper. You can add additional currency formats
* with CakeNumber::addFormat
*
* @var array
*/
protected static $_currencies = array(
'USD' => array(
'wholeSymbol' => '$', 'wholePosition' => 'before', 'fractionSymbol' => 'c', 'fractionPosition' => 'after',
'zero' => 0, 'places' => 2, 'thousands' => ',', 'decimals' => '.', 'negative' => '()', 'escape' => true
),
'GBP' => array(
'wholeSymbol' => '&#163;', 'wholePosition' => 'before', 'fractionSymbol' => 'p', 'fractionPosition' => 'after',
'zero' => 0, 'places' => 2, 'thousands' => ',', 'decimals' => '.', 'negative' => '()','escape' => false
),
'EUR' => array(
'wholeSymbol' => '&#8364;', 'wholePosition' => 'before', 'fractionSymbol' => false, 'fractionPosition' => 'after',
'zero' => 0, 'places' => 2, 'thousands' => '.', 'decimals' => ',', 'negative' => '()', 'escape' => false
)
);
/**
* Default options for currency formats
*
* @var array
*/
protected static $_currencyDefaults = array(
'wholeSymbol' => '', 'wholePosition' => 'before', 'fractionSymbol' => '', 'fractionPosition' => 'after',
'zero' => '0', 'places' => 2, 'thousands' => ',', 'decimals' => '.','negative' => '()', 'escape' => true,
);
/**
* Formats a number with a level of precision.
*
* @param float $number A floating point number.
* @param integer $precision The precision of the returned number.
* @return float Formatted float.
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::precision
*/
public function precision($number, $precision = 3) {
return sprintf("%01.{$precision}f", $number);
}
/**
* Returns a formatted-for-humans file size.
*
* @param integer $size Size in bytes
* @return string Human readable size
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::toReadableSize
*/
public function toReadableSize($size) {
switch (true) {
case $size < 1024:
return __dn('cake', '%d Byte', '%d Bytes', $size, $size);
case round($size / 1024) < 1024:
return __d('cake', '%d KB', $this->precision($size / 1024, 0));
case round($size / 1024 / 1024, 2) < 1024:
return __d('cake', '%.2f MB', $this->precision($size / 1024 / 1024, 2));
case round($size / 1024 / 1024 / 1024, 2) < 1024:
return __d('cake', '%.2f GB', $this->precision($size / 1024 / 1024 / 1024, 2));
default:
return __d('cake', '%.2f TB', $this->precision($size / 1024 / 1024 / 1024 / 1024, 2));
}
}
/**
* Formats a number into a percentage string.
*
* @param float $number A floating point number
* @param integer $precision The precision of the returned number
* @return string Percentage string
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::toPercentage
*/
public function toPercentage($number, $precision = 2) {
return $this->precision($number, $precision) . '%';
}
/**
* Formats a number into a currency format.
*
* @param float $number A floating point number
* @param integer $options if int then places, if string then before, if (,.-) then use it
* or array with places and before keys
* @return string formatted number
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::format
*/
public function format($number, $options = false) {
$places = 0;
if (is_int($options)) {
$places = $options;
}
$separators = array(',', '.', '-', ':');
$before = $after = null;
if (is_string($options) && !in_array($options, $separators)) {
$before = $options;
}
$thousands = ',';
if (!is_array($options) && in_array($options, $separators)) {
$thousands = $options;
}
$decimals = '.';
if (!is_array($options) && in_array($options, $separators)) {
$decimals = $options;
}
$escape = true;
if (is_array($options)) {
$options = array_merge(array('before' => '$', 'places' => 2, 'thousands' => ',', 'decimals' => '.'), $options);
extract($options);
}
$out = $before . number_format($number, $places, $decimals, $thousands) . $after;
if ($escape) {
return h($out);
}
return $out;
}
/**
* Formats a number into a currency format.
*
* ### Options
*
* - `before` - The currency symbol to place before whole numbers ie. '$'
* - `after` - The currency symbol to place after decimal numbers ie. 'c'. Set to boolean false to
* use no decimal symbol. eg. 0.35 => $0.35.
* - `zero` - The text to use for zero values, can be a string or a number. ie. 0, 'Free!'
* - `places` - Number of decimal places to use. ie. 2
* - `thousands` - Thousands separator ie. ','
* - `decimals` - Decimal separator symbol ie. '.'
* - `negative` - Symbol for negative numbers. If equal to '()', the number will be wrapped with ( and )
* - `escape` - Should the output be htmlentity escaped? Defaults to true
*
* @param float $number
* @param string $currency Shortcut to default options. Valid values are 'USD', 'EUR', 'GBP', otherwise
* set at least 'before' and 'after' options.
* @param array $options
* @return string Number formatted as a currency.
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::currency
*/
public function currency($number, $currency = 'USD', $options = array()) {
$default = self::$_currencyDefaults;
if (isset(self::$_currencies[$currency])) {
$default = self::$_currencies[$currency];
} elseif (is_string($currency)) {
$options['before'] = $currency;
}
$options = array_merge($default, $options);
if (isset($options['before']) && $options['before'] !== '') {
$options['wholeSymbol'] = $options['before'];
}
if (isset($options['after']) && !$options['after'] !== '') {
$options['fractionSymbol'] = $options['after'];
}
$result = $options['before'] = $options['after'] = null;
$symbolKey = 'whole';
if ($number == 0 ) {
if ($options['zero'] !== 0 ) {
return $options['zero'];
}
} elseif ($number < 1 && $number > -1 ) {
if ($options['fractionSymbol'] !== false) {
$multiply = intval('1' . str_pad('', $options['places'], '0'));
$number = $number * $multiply;
$options['places'] = null;
$symbolKey = 'fraction';
}
}
$position = $options[$symbolKey.'Position'] != 'after' ? 'before' : 'after';
$options[$position] = $options[$symbolKey.'Symbol'];
$abs = abs($number);
$result = $this->format($abs, $options);
if ($number < 0 ) {
if ($options['negative'] == '()') {
$result = '(' . $result .')';
} else {
$result = $options['negative'] . $result;
}
}
return $result;
}
/**
* Add a currency format to the Number helper. Makes reusing
* currency formats easier.
*
* {{{ $number->addFormat('NOK', array('before' => 'Kr. ')); }}}
*
* You can now use `NOK` as a shortform when formatting currency amounts.
*
* {{{ $number->currency($value, 'NOK'); }}}
*
* Added formats are merged with the following defaults.
*
* {{{
* array(
* 'before' => '$', 'after' => 'c', 'zero' => 0, 'places' => 2, 'thousands' => ',',
* 'decimals' => '.', 'negative' => '()', 'escape' => true
* )
* }}}
*
* @param string $formatName The format name to be used in the future.
* @param array $options The array of options for this format.
* @return void
* @see NumberHelper::currency()
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::addFormat
*/
public function addFormat($formatName, $options) {
self::$_currencies[$formatName] = $options + self::$_currencyDefaults;
}
}

View file

@ -0,0 +1,766 @@
<?php
/**
* CakeTime utility class file.
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* 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://cakephp.org CakePHP(tm) Project
* @package Cake.Utility
* @since CakePHP(tm) v 0.10.0.1076
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::uses('Multibyte', 'I18n');
/**
* Time Helper class for easy use of time data.
*
* Manipulation of time data.
*
* @package Cake.Utility
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html
*/
class CakeTime {
/**
* The format to use when formatting a time using `TimeHelper::nice()`
*
* The format should use the locale strings as defined in the PHP docs under
* `strftime` (http://php.net/manual/en/function.strftime.php)
*
* @var string
* @see TimeHelper::format()
*/
public $niceFormat = '%a, %b %eS %Y, %H:%M';
/**
* Converts a string representing the format for the function strftime and returns a
* windows safe and i18n aware format.
*
* @param string $format Format with specifiers for strftime function.
* Accepts the special specifier %S which mimics the modifier S for date()
* @param string $time UNIX timestamp
* @return string windows safe and date() function compatible format for strftime
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function convertSpecifiers($format, $time = null) {
if (!$time) {
$time = time();
}
$this->__time = $time;
return preg_replace_callback('/\%(\w+)/', array($this, '_translateSpecifier'), $format);
}
/**
* Auxiliary function to translate a matched specifier element from a regular expression into
* a windows safe and i18n aware specifier
*
* @param array $specifier match from regular expression
* @return string converted element
*/
protected function _translateSpecifier($specifier) {
switch ($specifier[1]) {
case 'a':
$abday = __dc('cake', 'abday', 5);
if (is_array($abday)) {
return $abday[date('w', $this->__time)];
}
break;
case 'A':
$day = __dc('cake', 'day', 5);
if (is_array($day)) {
return $day[date('w', $this->__time)];
}
break;
case 'c':
$format = __dc('cake', 'd_t_fmt', 5);
if ($format != 'd_t_fmt') {
return $this->convertSpecifiers($format, $this->__time);
}
break;
case 'C':
return sprintf("%02d", date('Y', $this->__time) / 100);
case 'D':
return '%m/%d/%y';
case 'e':
if (DS === '/') {
return '%e';
}
$day = date('j', $this->__time);
if ($day < 10) {
$day = ' ' . $day;
}
return $day;
case 'eS' :
return date('jS', $this->__time);
case 'b':
case 'h':
$months = __dc('cake', 'abmon', 5);
if (is_array($months)) {
return $months[date('n', $this->__time) -1];
}
return '%b';
case 'B':
$months = __dc('cake', 'mon', 5);
if (is_array($months)) {
return $months[date('n', $this->__time) -1];
}
break;
case 'n':
return "\n";
case 'p':
case 'P':
$default = array('am' => 0, 'pm' => 1);
$meridiem = $default[date('a', $this->__time)];
$format = __dc('cake', 'am_pm', 5);
if (is_array($format)) {
$meridiem = $format[$meridiem];
return ($specifier[1] == 'P') ? strtolower($meridiem) : strtoupper($meridiem);
}
break;
case 'r':
$complete = __dc('cake', 't_fmt_ampm', 5);
if ($complete != 't_fmt_ampm') {
return str_replace('%p', $this->_translateSpecifier(array('%p', 'p')), $complete);
}
break;
case 'R':
return date('H:i', $this->__time);
case 't':
return "\t";
case 'T':
return '%H:%M:%S';
case 'u':
return ($weekDay = date('w', $this->__time)) ? $weekDay : 7;
case 'x':
$format = __dc('cake', 'd_fmt', 5);
if ($format != 'd_fmt') {
return $this->convertSpecifiers($format, $this->__time);
}
break;
case 'X':
$format = __dc('cake', 't_fmt', 5);
if ($format != 't_fmt') {
return $this->convertSpecifiers($format, $this->__time);
}
break;
}
return $specifier[0];
}
/**
* Converts given time (in server's time zone) to user's local time, given his/her offset from GMT.
*
* @param string $serverTime UNIX timestamp
* @param integer $userOffset User's offset from GMT (in hours)
* @return integer UNIX timestamp
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function convert($serverTime, $userOffset) {
$serverOffset = $this->serverOffset();
$gmtTime = $serverTime - $serverOffset;
$userTime = $gmtTime + $userOffset * (60*60);
return $userTime;
}
/**
* Returns server's offset from GMT in seconds.
*
* @return integer Offset
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function serverOffset() {
return date('Z', time());
}
/**
* Returns a UNIX timestamp, given either a UNIX timestamp or a valid strtotime() date string.
*
* @param string $dateString Datetime string
* @param integer $userOffset User's offset from GMT (in hours)
* @return string Parsed timestamp
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function fromString($dateString, $userOffset = null) {
if (empty($dateString)) {
return false;
}
if (is_integer($dateString) || is_numeric($dateString)) {
$date = intval($dateString);
} else {
$date = strtotime($dateString);
}
if ($userOffset !== null) {
return $this->convert($date, $userOffset);
}
if ($date === -1) {
return false;
}
return $date;
}
/**
* Returns a nicely formatted date string for given Datetime string.
*
* See http://php.net/manual/en/function.strftime.php for information on formatting
* using locale strings.
*
* @param string $dateString Datetime string or Unix timestamp
* @param integer $userOffset User's offset from GMT (in hours)
* @param string $format The format to use. If null, `TimeHelper::$niceFormat` is used
* @return string Formatted date string
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function nice($dateString = null, $userOffset = null, $format = null) {
if ($dateString != null) {
$date = $this->fromString($dateString, $userOffset);
} else {
$date = time();
}
if (!$format) {
$format = $this->niceFormat;
}
$format = $this->convertSpecifiers($format, $date);
return $this->_strftime($format, $date);
}
/**
* Returns a formatted descriptive date string for given datetime string.
*
* If the given date is today, the returned string could be "Today, 16:54".
* If the given date was yesterday, the returned string could be "Yesterday, 16:54".
* If $dateString's year is the current year, the returned string does not
* include mention of the year.
*
* @param string $dateString Datetime string or Unix timestamp
* @param integer $userOffset User's offset from GMT (in hours)
* @return string Described, relative date string
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function niceShort($dateString = null, $userOffset = null) {
$date = $dateString ? $this->fromString($dateString, $userOffset) : time();
$y = $this->isThisYear($date) ? '' : ' %Y';
if ($this->isToday($dateString, $userOffset)) {
$ret = __d('cake', 'Today, %s', $this->_strftime("%H:%M", $date));
} elseif ($this->wasYesterday($dateString, $userOffset)) {
$ret = __d('cake', 'Yesterday, %s', $this->_strftime("%H:%M", $date));
} else {
$format = $this->convertSpecifiers("%b %eS{$y}, %H:%M", $date);
$ret = $this->_strftime($format, $date);
}
return $ret;
}
/**
* Returns a partial SQL string to search for all records between two dates.
*
* @param string $begin Datetime string or Unix timestamp
* @param string $end Datetime string or Unix timestamp
* @param string $fieldName Name of database field to compare with
* @param integer $userOffset User's offset from GMT (in hours)
* @return string Partial SQL string.
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function daysAsSql($begin, $end, $fieldName, $userOffset = null) {
$begin = $this->fromString($begin, $userOffset);
$end = $this->fromString($end, $userOffset);
$begin = date('Y-m-d', $begin) . ' 00:00:00';
$end = date('Y-m-d', $end) . ' 23:59:59';
return "($fieldName >= '$begin') AND ($fieldName <= '$end')";
}
/**
* Returns a partial SQL string to search for all records between two times
* occurring on the same day.
*
* @param string $dateString Datetime string or Unix timestamp
* @param string $fieldName Name of database field to compare with
* @param integer $userOffset User's offset from GMT (in hours)
* @return string Partial SQL string.
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function dayAsSql($dateString, $fieldName, $userOffset = null) {
$date = $this->fromString($dateString, $userOffset);
return $this->daysAsSql($dateString, $dateString, $fieldName);
}
/**
* Returns true if given datetime string is today.
*
* @param string $dateString Datetime string or Unix timestamp
* @param integer $userOffset User's offset from GMT (in hours)
* @return boolean True if datetime string is today
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#testing-time
*/
public function isToday($dateString, $userOffset = null) {
$date = $this->fromString($dateString, $userOffset);
return date('Y-m-d', $date) == date('Y-m-d', time());
}
/**
* Returns true if given datetime string is within this week.
*
* @param string $dateString
* @param integer $userOffset User's offset from GMT (in hours)
* @return boolean True if datetime string is within current week
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#testing-time
*/
public function isThisWeek($dateString, $userOffset = null) {
$date = $this->fromString($dateString, $userOffset);
return date('W o', $date) == date('W o', time());
}
/**
* Returns true if given datetime string is within this month
* @param string $dateString
* @param integer $userOffset User's offset from GMT (in hours)
* @return boolean True if datetime string is within current month
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#testing-time
*/
public function isThisMonth($dateString, $userOffset = null) {
$date = $this->fromString($dateString);
return date('m Y', $date) == date('m Y', time());
}
/**
* Returns true if given datetime string is within current year.
*
* @param string $dateString Datetime string or Unix timestamp
* @param integer $userOffset User's offset from GMT (in hours)
* @return boolean True if datetime string is within current year
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#testing-time
*/
public function isThisYear($dateString, $userOffset = null) {
$date = $this->fromString($dateString, $userOffset);
return date('Y', $date) == date('Y', time());
}
/**
* Returns true if given datetime string was yesterday.
*
* @param string $dateString Datetime string or Unix timestamp
* @param integer $userOffset User's offset from GMT (in hours)
* @return boolean True if datetime string was yesterday
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#testing-time
*
*/
public function wasYesterday($dateString, $userOffset = null) {
$date = $this->fromString($dateString, $userOffset);
return date('Y-m-d', $date) == date('Y-m-d', strtotime('yesterday'));
}
/**
* Returns true if given datetime string is tomorrow.
*
* @param string $dateString Datetime string or Unix timestamp
* @param integer $userOffset User's offset from GMT (in hours)
* @return boolean True if datetime string was yesterday
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#testing-time
*/
public function isTomorrow($dateString, $userOffset = null) {
$date = $this->fromString($dateString, $userOffset);
return date('Y-m-d', $date) == date('Y-m-d', strtotime('tomorrow'));
}
/**
* Returns the quarter
*
* @param string $dateString
* @param boolean $range if true returns a range in Y-m-d format
* @return mixed 1, 2, 3, or 4 quarter of year or array if $range true
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function toQuarter($dateString, $range = false) {
$time = $this->fromString($dateString);
$date = ceil(date('m', $time) / 3);
if ($range === true) {
$range = 'Y-m-d';
}
if ($range !== false) {
$year = date('Y', $time);
switch ($date) {
case 1:
$date = array($year.'-01-01', $year.'-03-31');
break;
case 2:
$date = array($year.'-04-01', $year.'-06-30');
break;
case 3:
$date = array($year.'-07-01', $year.'-09-30');
break;
case 4:
$date = array($year.'-10-01', $year.'-12-31');
break;
}
}
return $date;
}
/**
* Returns a UNIX timestamp from a textual datetime description. Wrapper for PHP function strtotime().
*
* @param string $dateString Datetime string to be represented as a Unix timestamp
* @param integer $userOffset User's offset from GMT (in hours)
* @return integer Unix timestamp
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function toUnix($dateString, $userOffset = null) {
return $this->fromString($dateString, $userOffset);
}
/**
* Returns a date formatted for Atom RSS feeds.
*
* @param string $dateString Datetime string or Unix timestamp
* @param integer $userOffset User's offset from GMT (in hours)
* @return string Formatted date string
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function toAtom($dateString, $userOffset = null) {
$date = $this->fromString($dateString, $userOffset);
return date('Y-m-d\TH:i:s\Z', $date);
}
/**
* Formats date for RSS feeds
*
* @param string $dateString Datetime string or Unix timestamp
* @param integer $userOffset User's offset from GMT (in hours)
* @return string Formatted date string
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function toRSS($dateString, $userOffset = null) {
$date = $this->fromString($dateString, $userOffset);
if (!is_null($userOffset)) {
if ($userOffset == 0) {
$timezone = '+0000';
} else {
$hours = (int) floor(abs($userOffset));
$minutes = (int) (fmod(abs($userOffset), $hours) * 60);
$timezone = ($userOffset < 0 ? '-' : '+') . str_pad($hours, 2, '0', STR_PAD_LEFT) . str_pad($minutes, 2, '0', STR_PAD_LEFT);
}
return date('D, d M Y H:i:s', $date) . ' ' . $timezone;
}
return date("r", $date);
}
/**
* Returns either a relative date or a formatted date depending
* on the difference between the current time and given datetime.
* $datetime should be in a <i>strtotime</i> - parsable format, like MySQL's datetime datatype.
*
* ### Options:
*
* - `format` => a fall back format if the relative time is longer than the duration specified by end
* - `end` => The end of relative time telling
* - `userOffset` => Users offset from GMT (in hours)
*
* Relative dates look something like this:
* 3 weeks, 4 days ago
* 15 seconds ago
*
* Default date formatting is d/m/yy e.g: on 18/2/09
*
* The returned string includes 'ago' or 'on' and assumes you'll properly add a word
* like 'Posted ' before the function output.
*
* @param string $dateTime Datetime string or Unix timestamp
* @param array $options Default format if timestamp is used in $dateString
* @return string Relative time string.
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function timeAgoInWords($dateTime, $options = array()) {
$userOffset = null;
if (is_array($options) && isset($options['userOffset'])) {
$userOffset = $options['userOffset'];
}
$now = time();
if (!is_null($userOffset)) {
$now = $this->convert(time(), $userOffset);
}
$inSeconds = $this->fromString($dateTime, $userOffset);
$backwards = ($inSeconds > $now);
$format = 'j/n/y';
$end = '+1 month';
if (is_array($options)) {
if (isset($options['format'])) {
$format = $options['format'];
unset($options['format']);
}
if (isset($options['end'])) {
$end = $options['end'];
unset($options['end']);
}
} else {
$format = $options;
}
if ($backwards) {
$futureTime = $inSeconds;
$pastTime = $now;
} else {
$futureTime = $now;
$pastTime = $inSeconds;
}
$diff = $futureTime - $pastTime;
// If more than a week, then take into account the length of months
if ($diff >= 604800) {
$current = array();
$date = array();
list($future['H'], $future['i'], $future['s'], $future['d'], $future['m'], $future['Y']) = explode('/', date('H/i/s/d/m/Y', $futureTime));
list($past['H'], $past['i'], $past['s'], $past['d'], $past['m'], $past['Y']) = explode('/', date('H/i/s/d/m/Y', $pastTime));
$years = $months = $weeks = $days = $hours = $minutes = $seconds = 0;
if ($future['Y'] == $past['Y'] && $future['m'] == $past['m']) {
$months = 0;
$years = 0;
} else {
if ($future['Y'] == $past['Y']) {
$months = $future['m'] - $past['m'];
} else {
$years = $future['Y'] - $past['Y'];
$months = $future['m'] + ((12 * $years) - $past['m']);
if ($months >= 12) {
$years = floor($months / 12);
$months = $months - ($years * 12);
}
if ($future['m'] < $past['m'] && $future['Y'] - $past['Y'] == 1) {
$years --;
}
}
}
if ($future['d'] >= $past['d']) {
$days = $future['d'] - $past['d'];
} else {
$daysInPastMonth = date('t', $pastTime);
$daysInFutureMonth = date('t', mktime(0, 0, 0, $future['m'] - 1, 1, $future['Y']));
if (!$backwards) {
$days = ($daysInPastMonth - $past['d']) + $future['d'];
} else {
$days = ($daysInFutureMonth - $past['d']) + $future['d'];
}
if ($future['m'] != $past['m']) {
$months --;
}
}
if ($months == 0 && $years >= 1 && $diff < ($years * 31536000)) {
$months = 11;
$years --;
}
if ($months >= 12) {
$years = $years + 1;
$months = $months - 12;
}
if ($days >= 7) {
$weeks = floor($days / 7);
$days = $days - ($weeks * 7);
}
} else {
$years = $months = $weeks = 0;
$days = floor($diff / 86400);
$diff = $diff - ($days * 86400);
$hours = floor($diff / 3600);
$diff = $diff - ($hours * 3600);
$minutes = floor($diff / 60);
$diff = $diff - ($minutes * 60);
$seconds = $diff;
}
$relativeDate = '';
$diff = $futureTime - $pastTime;
if ($diff > abs($now - $this->fromString($end))) {
$relativeDate = __d('cake', 'on %s', date($format, $inSeconds));
} else {
if ($years > 0) {
// years and months and days
$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d year', '%d years', $years, $years);
$relativeDate .= $months > 0 ? ($relativeDate ? ', ' : '') . __dn('cake', '%d month', '%d months', $months, $months) : '';
$relativeDate .= $weeks > 0 ? ($relativeDate ? ', ' : '') . __dn('cake', '%d week', '%d weeks', $weeks, $weeks) : '';
$relativeDate .= $days > 0 ? ($relativeDate ? ', ' : '') . __dn('cake', '%d day', '%d days', $days, $days) : '';
} elseif (abs($months) > 0) {
// months, weeks and days
$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d month', '%d months', $months, $months);
$relativeDate .= $weeks > 0 ? ($relativeDate ? ', ' : '') . __dn('cake', '%d week', '%d weeks', $weeks, $weeks) : '';
$relativeDate .= $days > 0 ? ($relativeDate ? ', ' : '') . __dn('cake', '%d day', '%d days', $days, $days) : '';
} elseif (abs($weeks) > 0) {
// weeks and days
$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d week', '%d weeks', $weeks, $weeks);
$relativeDate .= $days > 0 ? ($relativeDate ? ', ' : '') . __dn('cake', '%d day', '%d days', $days, $days) : '';
} elseif (abs($days) > 0) {
// days and hours
$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d day', '%d days', $days, $days);
$relativeDate .= $hours > 0 ? ($relativeDate ? ', ' : '') . __dn('cake', '%d hour', '%d hours', $hours, $hours) : '';
} elseif (abs($hours) > 0) {
// hours and minutes
$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d hour', '%d hours', $hours, $hours);
$relativeDate .= $minutes > 0 ? ($relativeDate ? ', ' : '') . __dn('cake', '%d minute', '%d minutes', $minutes, $minutes) : '';
} elseif (abs($minutes) > 0) {
// minutes only
$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d minute', '%d minutes', $minutes, $minutes);
} else {
// seconds only
$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d second', '%d seconds', $seconds, $seconds);
}
if (!$backwards) {
$relativeDate = __d('cake', '%s ago', $relativeDate);
}
}
return $relativeDate;
}
/**
* Returns true if specified datetime was within the interval specified, else false.
*
* @param mixed $timeInterval the numeric value with space then time type.
* Example of valid types: 6 hours, 2 days, 1 minute.
* @param mixed $dateString the datestring or unix timestamp to compare
* @param integer $userOffset User's offset from GMT (in hours)
* @return boolean
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#testing-time
*/
public function wasWithinLast($timeInterval, $dateString, $userOffset = null) {
$tmp = str_replace(' ', '', $timeInterval);
if (is_numeric($tmp)) {
$timeInterval = $tmp . ' ' . __d('cake', 'days');
}
$date = $this->fromString($dateString, $userOffset);
$interval = $this->fromString('-' . $timeInterval);
if ($date >= $interval && $date <= time()) {
return true;
}
return false;
}
/**
* Returns gmt as a UNIX timestamp.
*
* @param string $string UNIX timestamp or a valid strtotime() date string
* @return integer UNIX timestamp
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function gmt($string = null) {
if ($string != null) {
$string = $this->fromString($string);
} else {
$string = time();
}
$hour = intval(date("G", $string));
$minute = intval(date("i", $string));
$second = intval(date("s", $string));
$month = intval(date("n", $string));
$day = intval(date("j", $string));
$year = intval(date("Y", $string));
return gmmktime($hour, $minute, $second, $month, $day, $year);
}
/**
* Returns a formatted date string, given either a UNIX timestamp or a valid strtotime() date string.
* This function also accepts a time string and a format string as first and second parameters.
* In that case this function behaves as a wrapper for TimeHelper::i18nFormat()
*
* @param string $format date format string (or a DateTime string)
* @param string $date Datetime string (or a date format string)
* @param boolean $invalid flag to ignore results of fromString == false
* @param integer $userOffset User's offset from GMT (in hours)
* @return string Formatted date string
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function format($format, $date = null, $invalid = false, $userOffset = null) {
$time = $this->fromString($date, $userOffset);
$_time = $this->fromString($format, $userOffset);
if (is_numeric($_time) && $time === false) {
$format = $date;
return $this->i18nFormat($_time, $format, $invalid, $userOffset);
}
if ($time === false && $invalid !== false) {
return $invalid;
}
return date($format, $time);
}
/**
* Returns a formatted date string, given either a UNIX timestamp or a valid strtotime() date string.
* It take in account the default date format for the current language if a LC_TIME file is used.
*
* @param string $date Datetime string
* @param string $format strftime format string.
* @param boolean $invalid flag to ignore results of fromString == false
* @param integer $userOffset User's offset from GMT (in hours)
* @return string Formatted and translated date string
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function i18nFormat($date, $format = null, $invalid = false, $userOffset = null) {
$date = $this->fromString($date, $userOffset);
if ($date === false && $invalid !== false) {
return $invalid;
}
if (empty($format)) {
$format = '%x';
}
$format = $this->convertSpecifiers($format, $date);
return $this->_strftime($format, $date);
}
/**
* Multibyte wrapper for strftime.
*
* Handles utf8_encoding the result of strftime when necessary.
*
* @param string $format Format string.
* @param int $date Timestamp to format.
* @return string formatted string with correct encoding.
*/
protected function _strftime($format, $date) {
$format = strftime($format, $date);
$encoding = Configure::read('App.encoding');
if (!empty($encoding) && $encoding === 'UTF-8') {
if (function_exists('mb_check_encoding')) {
$valid = mb_check_encoding($format, $encoding);
} else {
$valid = !Multibyte::checkMultibyte($format);
}
if (!$valid) {
$format = utf8_encode($format);
}
}
return $format;
}
}

View file

@ -241,6 +241,11 @@ class Debugger {
$error = 'Notice';
$level = LOG_NOTICE;
break;
case E_DEPRECATED:
case E_USER_DEPRECATED:
$error = 'Deprecated';
$level = LOG_NOTICE;
break;
default:
return;
break;
@ -805,5 +810,4 @@ class Debugger {
trigger_error(__d('cake_dev', 'Please change the value of \'Security.cipherSeed\' in app/Config/core.php to a numeric (digits only) seed value specific to your application'), E_USER_NOTICE);
}
}
}

View file

@ -352,4 +352,252 @@ class String {
}
return $wrapped;
}
/**
* Highlights a given phrase in a text. You can specify any expression in highlighter that
* may include the \1 expression to include the $phrase found.
*
* ### Options:
*
* - `format` The piece of html with that the phrase will be highlighted
* - `html` If true, will ignore any HTML tags, ensuring that only the correct text is highlighted
*
* @param string $text Text to search the phrase in
* @param string $phrase The phrase that will be searched
* @param array $options An array of html attributes and options.
* @return string The highlighted text
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::highlight
*/
public function highlight($text, $phrase, $options = array()) {
if (empty($phrase)) {
return $text;
}
$default = array(
'format' => '<span class="highlight">\1</span>',
'html' => false
);
$options = array_merge($default, $options);
extract($options);
if (is_array($phrase)) {
$replace = array();
$with = array();
foreach ($phrase as $key => $segment) {
$segment = '(' . preg_quote($segment, '|') . ')';
if ($html) {
$segment = "(?![^<]+>)$segment(?![^<]+>)";
}
$with[] = (is_array($format)) ? $format[$key] : $format;
$replace[] = "|$segment|iu";
}
return preg_replace($replace, $with, $text);
} else {
$phrase = '(' . preg_quote($phrase, '|') . ')';
if ($html) {
$phrase = "(?![^<]+>)$phrase(?![^<]+>)";
}
return preg_replace("|$phrase|iu", $format, $text);
}
}
/**
* Strips given text of all links (<a href=....)
*
* @param string $text Text
* @return string The text without links
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::stripLinks
*/
public function stripLinks($text) {
return preg_replace('|<a\s+[^>]+>|im', '', preg_replace('|<\/a>|im', '', $text));
}
/**
* Truncates text.
*
* Cuts a string to the length of $length and replaces the last characters
* with the ending if the text is longer than length.
*
* ### Options:
*
* - `ending` Will be used as Ending and appended to the trimmed string
* - `exact` If false, $text will not be cut mid-word
* - `html` If true, HTML tags would be handled correctly
*
* @param string $text String to truncate.
* @param integer $length Length of returned string, including ellipsis.
* @param array $options An array of html attributes and options.
* @return string Trimmed string.
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::truncate
*/
public function truncate($text, $length = 100, $options = array()) {
$default = array(
'ending' => '...', 'exact' => true, 'html' => false
);
$options = array_merge($default, $options);
extract($options);
if (!function_exists('mb_strlen')) {
class_exists('Multibyte');
}
if ($html) {
if (mb_strlen(preg_replace('/<.*?>/', '', $text)) <= $length) {
return $text;
}
$totalLength = mb_strlen(strip_tags($ending));
$openTags = array();
$truncate = '';
preg_match_all('/(<\/?([\w+]+)[^>]*>)?([^<>]*)/', $text, $tags, PREG_SET_ORDER);
foreach ($tags as $tag) {
if (!preg_match('/img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param/s', $tag[2])) {
if (preg_match('/<[\w]+[^>]*>/s', $tag[0])) {
array_unshift($openTags, $tag[2]);
} else if (preg_match('/<\/([\w]+)[^>]*>/s', $tag[0], $closeTag)) {
$pos = array_search($closeTag[1], $openTags);
if ($pos !== false) {
array_splice($openTags, $pos, 1);
}
}
}
$truncate .= $tag[1];
$contentLength = mb_strlen(preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', ' ', $tag[3]));
if ($contentLength + $totalLength > $length) {
$left = $length - $totalLength;
$entitiesLength = 0;
if (preg_match_all('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', $tag[3], $entities, PREG_OFFSET_CAPTURE)) {
foreach ($entities[0] as $entity) {
if ($entity[1] + 1 - $entitiesLength <= $left) {
$left--;
$entitiesLength += mb_strlen($entity[0]);
} else {
break;
}
}
}
$truncate .= mb_substr($tag[3], 0 , $left + $entitiesLength);
break;
} else {
$truncate .= $tag[3];
$totalLength += $contentLength;
}
if ($totalLength >= $length) {
break;
}
}
} else {
if (mb_strlen($text) <= $length) {
return $text;
} else {
$truncate = mb_substr($text, 0, $length - mb_strlen($ending));
}
}
if (!$exact) {
$spacepos = mb_strrpos($truncate, ' ');
if ($html) {
$truncateCheck = mb_substr($truncate, 0, $spacepos);
$lastOpenTag = mb_strrpos($truncateCheck, '<');
$lastCloseTag = mb_strrpos($truncateCheck, '>');
if ($lastOpenTag > $lastCloseTag) {
preg_match_all('/<[\w]+[^>]*>/s', $truncate, $lastTagMatches);
$lastTag = array_pop($lastTagMatches[0]);
$spacepos = mb_strrpos($truncate, $lastTag) + mb_strlen($lastTag);
}
$bits = mb_substr($truncate, $spacepos);
preg_match_all('/<\/([a-z]+)>/', $bits, $droppedTags, PREG_SET_ORDER);
if (!empty($droppedTags)) {
if (!empty($openTags)) {
foreach ($droppedTags as $closingTag) {
if (!in_array($closingTag[1], $openTags)) {
array_unshift($openTags, $closingTag[1]);
}
}
} else {
foreach ($droppedTags as $closingTag) {
array_push($openTags, $closingTag[1]);
}
}
}
}
$truncate = mb_substr($truncate, 0, $spacepos);
}
$truncate .= $ending;
if ($html) {
foreach ($openTags as $tag) {
$truncate .= '</' . $tag . '>';
}
}
return $truncate;
}
/**
* Extracts an excerpt from the text surrounding the phrase with a number of characters on each side
* determined by radius.
*
* @param string $text String to search the phrase in
* @param string $phrase Phrase that will be searched for
* @param integer $radius The amount of characters that will be returned on each side of the founded phrase
* @param string $ending Ending that will be appended
* @return string Modified string
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::excerpt
*/
public function excerpt($text, $phrase, $radius = 100, $ending = '...') {
if (empty($text) or empty($phrase)) {
return $this->truncate($text, $radius * 2, array('ending' => $ending));
}
$append = $prepend = $ending;
$phraseLen = mb_strlen($phrase);
$textLen = mb_strlen($text);
$pos = mb_strpos(mb_strtolower($text), mb_strtolower($phrase));
if ($pos === false) {
return mb_substr($text, 0, $radius) . $ending;
}
$startPos = $pos - $radius;
if ($startPos <= 0) {
$startPos = 0;
$prepend = '';
}
$endPos = $pos + $phraseLen + $radius;
if ($endPos >= $textLen) {
$endPos = $textLen;
$append = '';
}
$excerpt = mb_substr($text, $startPos, $endPos - $startPos);
$excerpt = $prepend . $excerpt . $append;
return $excerpt;
}
/**
* Creates a comma separated list where the last two items are joined with 'and', forming natural English
*
* @param array $list The list to be joined
* @param string $and The word used to join the last and second last items together with. Defaults to 'and'
* @param string $separator The separator used to join all the other items together. Defaults to ', '
* @return string The glued together string.
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::toList
*/
public function toList($list, $and = 'and', $separator = ', ') {
if (count($list) > 1) {
return implode($separator, array_slice($list, null, -1)) . ' ' . $and . ' ' . array_pop($list);
} else {
return array_pop($list);
}
}
}

View file

@ -37,7 +37,7 @@ if ($noLogs || isset($_forced_from_dbo_)):
foreach ($logs as $source => $logInfo):
$text = $logInfo['count'] > 1 ? 'queries' : 'query';
printf(
'<table class="cake-sql-log" id="cakeSqlLog_%s" summary="Cake SQL Log" cellspacing="0" border = "0">',
'<table class="cake-sql-log" id="cakeSqlLog_%s" summary="Cake SQL Log" cellspacing="0">',
preg_replace('/[^A-Za-z0-9_]/', '_', uniqid(time(), true))
);
printf('<caption>(%s) %s %s took %s ms</caption>', $source, $logInfo['count'], $text, $logInfo['time']);
@ -49,13 +49,13 @@ if ($noLogs || isset($_forced_from_dbo_)):
<?php
foreach ($logInfo['log'] as $k => $i) :
$i += array('error' => '');
if(!empty($i['params']) && is_array($i['params'])) {
if (!empty($i['params']) && is_array($i['params'])) {
$bindParam = $bindType = null;
if(preg_match('/.+ :.+/', $i['query'])) {
if (preg_match('/.+ :.+/', $i['query'])) {
$bindType = true;
}
foreach($i['params'] as $bindKey => $bindVal) {
if($bindType === true) {
foreach ($i['params'] as $bindKey => $bindVal) {
if ($bindType === true) {
$bindParam .= h($bindKey) ." => " . h($bindVal) . ", ";
} else {
$bindParam .= h($bindVal) . ", ";

View file

@ -271,7 +271,7 @@ class Helper extends Object {
* `plugin` False value will prevent parsing path as a plugin
* @return string Generated url
*/
public function assetUrl($path, array $options) {
public function assetUrl($path, $options = array()) {
if (is_array($path)) {
$path = $this->url($path, !empty($options['fullBase']));
} elseif (strpos($path, '://') === false) {

View file

@ -272,8 +272,8 @@ class FormHelper extends AppHelper {
* Returns false if given form field described by the current entity has no errors.
* Otherwise it returns the validation message
*
* @return mixed Either false when there or no errors, or the error
* string. The error string could be ''.
* @return mixed Either false when there or no errors, or an array of error
* strings. An error string could be ''.
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::tagIsInvalid
*/
public function tagIsInvalid() {
@ -289,8 +289,8 @@ class FormHelper extends AppHelper {
if (empty($errors)) {
return false;
}
$error = Set::classicExtract($errors, join('.', $entity));
return $error === null ? false : $error;
$errors = Set::classicExtract($errors, join('.', $entity));
return $errors === null ? false : $errors;
}
/**
@ -739,7 +739,7 @@ class FormHelper extends AppHelper {
*
* ### Options
*
* - `for` - Set the for attribute, if its not defined the for attribute
* - `for` - Set the for attribute, if its not defined the for attribute
* will be generated from the $fieldName parameter using
* FormHelper::domId().
*
@ -776,8 +776,8 @@ class FormHelper extends AppHelper {
* }}}
*
* @param string $fieldName This should be "Modelname.fieldname"
* @param string $text Text that will appear in the label field. If
* $text is left undefined the text will be inflected from the
* @param string $text Text that will appear in the label field. If
* $text is left undefined the text will be inflected from the
* fieldName.
* @param mixed $options An array of HTML attributes, or a string, to be used as a class name.
* @return string The formatted LABEL element

View file

@ -991,9 +991,9 @@ class HtmlHelper extends AppHelper {
* Using multiple video files:
*
* {{{
* echo $this->Html->video(
* echo $this->Html->media(
* array('video.mp4', array('src' => 'video.ogv', 'type' => "video/ogg; codecs='theora, vorbis'")),
* array('type' => 'video', 'autoplay')
* array('tag' => 'video', 'autoplay')
* );
* }}}
*
@ -1008,8 +1008,8 @@ class HtmlHelper extends AppHelper {
*
* ### Options
*
* - `type` Type of media element to generate, valid values are "audio" or "video".
* If type is not provided media type is guessed based on file's mime type.
* - `tag` Type of media element to generate, either "audio" or "video".
* If tag is not provided it's guessed based on file's mime type.
* - `text` Text to include inside the audio/video tag
* - `pathPrefix` Path prefix to use for relative urls, defaults to 'files/'
* - `fullBase` If provided the src attribute will get a full address including domain name
@ -1017,15 +1017,19 @@ class HtmlHelper extends AppHelper {
* @param string|array $path Path to the video file, relative to the webroot/{$options['pathPrefix']} directory.
* Or an array where each item itself can be a path string or an associate array containing keys `src` and `type`
* @param array $options Array of HTML attributes, and special options above.
* @return string Generated video tag
* @return string Generated media element
*/
public function media($path, $options = array()) {
$options += array('type' => null, 'pathPrefix' => 'files/', 'text' => '');
$options += array(
'tag' => null,
'pathPrefix' => 'files/',
'text' => ''
);
if (!empty($options['type'])) {
$type = $options['type'];
if (!empty($options['tag'])) {
$tag = $options['tag'];
} else {
$type = null;
$tag = null;
}
if (is_array($path)) {
@ -1047,19 +1051,22 @@ class HtmlHelper extends AppHelper {
$options['text'] = $sourceTags . $options['text'];
unset($options['fullBase']);
} else {
if (empty($path) && !empty($options['src'])) {
$path = $options['src'];
}
$options['src'] = $this->assetUrl($path, $options);
}
if ($type === null) {
if ($tag === null) {
if (is_array($path)) {
$mimeType = $path[0]['type'];
} else {
$mimeType = $this->response->getMimeType(pathinfo($path, PATHINFO_EXTENSION));
}
if (preg_match('#^video/#', $mimeType)) {
$type = 'video';
$tag = 'video';
} else {
$type = 'audio';
$tag = 'audio';
}
}
@ -1069,12 +1076,12 @@ class HtmlHelper extends AppHelper {
$text = $options['text'];
$options = array_diff_key($options, array(
'type' => '',
'tag' => '',
'fullBase' => '',
'pathPrefix' => '',
'text' => ''
));
return $this->tag($type, $text, $options);
return $this->tag($tag, $text, $options);
}
/**

View file

@ -19,6 +19,7 @@
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::uses('CakeNumber', 'Utility');
App::uses('AppHelper', 'View/Helper');
/**
@ -28,42 +29,33 @@ App::uses('AppHelper', 'View/Helper');
*
* @package Cake.View.Helper
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html
* @see CakeNumber
*/
class NumberHelper extends AppHelper {
/**
* Currencies supported by the helper. You can add additional currency formats
* with NumberHelper::addFormat
*
* @var array
*/
protected $_currencies = array(
'USD' => array(
'wholeSymbol' => '$', 'wholePosition' => 'before', 'fractionSymbol' => 'c', 'fractionPosition' => 'after',
'zero' => 0, 'places' => 2, 'thousands' => ',', 'decimals' => '.', 'negative' => '()', 'escape' => true
),
'GBP' => array(
'wholeSymbol' => '&#163;', 'wholePosition' => 'before', 'fractionSymbol' => 'p', 'fractionPosition' => 'after',
'zero' => 0, 'places' => 2, 'thousands' => ',', 'decimals' => '.', 'negative' => '()','escape' => false
),
'EUR' => array(
'wholeSymbol' => '&#8364;', 'wholePosition' => 'before', 'fractionSymbol' => false, 'fractionPosition' => 'after',
'zero' => 0, 'places' => 2, 'thousands' => '.', 'decimals' => ',', 'negative' => '()', 'escape' => false
)
);
/** CakeNumber instance
*/
protected $_CakeNumber = null;
/* Default Constructor
*
* @param View $View The View this helper is being attached to.
* @param array $settings Configuration settings for the helper
*/
function __construct(View $View, $settings = array()) {
parent::__construct($View, $settings);
$this->_CakeNumber = new CakeNumber();
}
/**
* Call methods from CakeNumber utility class
*/
function __call($method, $params) {
return call_user_func_array(array($this->_CakeNumber, $method), $params);
}
/**
* Default options for currency formats
*
* @var array
*/
protected $_currencyDefaults = array(
'wholeSymbol' => '', 'wholePosition' => 'before', 'fractionSymbol' => '', 'fractionPosition' => 'after',
'zero' => '0', 'places' => 2, 'thousands' => ',', 'decimals' => '.','negative' => '()', 'escape' => true,
);
/**
* Formats a number with a level of precision.
* @see: CakeNumber::precision()
*
* @param float $number A floating point number.
* @param integer $precision The precision of the returned number.
@ -71,33 +63,22 @@ class NumberHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::precision
*/
public function precision($number, $precision = 3) {
return sprintf("%01.{$precision}f", $number);
return $this->_CakeNumber->precision($number, $precision);
}
/**
* Returns a formatted-for-humans file size.
* @see: CakeNumber::toReadableSize()
*
* @param integer $size Size in bytes
* @return string Human readable size
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::toReadableSize
*/
public function toReadableSize($size) {
switch (true) {
case $size < 1024:
return __dn('cake', '%d Byte', '%d Bytes', $size, $size);
case round($size / 1024) < 1024:
return __d('cake', '%d KB', $this->precision($size / 1024, 0));
case round($size / 1024 / 1024, 2) < 1024:
return __d('cake', '%.2f MB', $this->precision($size / 1024 / 1024, 2));
case round($size / 1024 / 1024 / 1024, 2) < 1024:
return __d('cake', '%.2f GB', $this->precision($size / 1024 / 1024 / 1024, 2));
default:
return __d('cake', '%.2f TB', $this->precision($size / 1024 / 1024 / 1024 / 1024, 2));
}
return $this->_CakeNumber->toReadableSize($size);
}
/**
* Formats a number into a percentage string.
* @see: CakeNumber::toPercentage()
*
* @param float $number A floating point number
* @param integer $precision The precision of the returned number
@ -105,11 +86,11 @@ class NumberHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::toPercentage
*/
public function toPercentage($number, $precision = 2) {
return $this->precision($number, $precision) . '%';
return $this->_CakeNumber->toPercentage($number, $precision);
}
/**
* Formats a number into a currency format.
* @see: CakeNumber::format()
*
* @param float $number A floating point number
* @param integer $options if int then places, if string then before, if (,.-) then use it
@ -118,54 +99,11 @@ class NumberHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::format
*/
public function format($number, $options = false) {
$places = 0;
if (is_int($options)) {
$places = $options;
}
$separators = array(',', '.', '-', ':');
$before = $after = null;
if (is_string($options) && !in_array($options, $separators)) {
$before = $options;
}
$thousands = ',';
if (!is_array($options) && in_array($options, $separators)) {
$thousands = $options;
}
$decimals = '.';
if (!is_array($options) && in_array($options, $separators)) {
$decimals = $options;
}
$escape = true;
if (is_array($options)) {
$options = array_merge(array('before' => '$', 'places' => 2, 'thousands' => ',', 'decimals' => '.'), $options);
extract($options);
}
$out = $before . number_format($number, $places, $decimals, $thousands) . $after;
if ($escape) {
return h($out);
}
return $out;
return $this->_CakeNumber->format($number, $options);
}
/**
* Formats a number into a currency format.
*
* ### Options
*
* - `before` - The currency symbol to place before whole numbers ie. '$'
* - `after` - The currency symbol to place after decimal numbers ie. 'c'. Set to boolean false to
* use no decimal symbol. eg. 0.35 => $0.35.
* - `zero` - The text to use for zero values, can be a string or a number. ie. 0, 'Free!'
* - `places` - Number of decimal places to use. ie. 2
* - `thousands` - Thousands separator ie. ','
* - `decimals` - Decimal separator symbol ie. '.'
* - `negative` - Symbol for negative numbers. If equal to '()', the number will be wrapped with ( and )
* - `escape` - Should the output be htmlentity escaped? Defaults to true
* @see: CakeNumber::currency()
*
* @param float $number
* @param string $currency Shortcut to default options. Valid values are 'USD', 'EUR', 'GBP', otherwise
@ -175,73 +113,11 @@ class NumberHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::currency
*/
public function currency($number, $currency = 'USD', $options = array()) {
$default = $this->_currencyDefaults;
if (isset($this->_currencies[$currency])) {
$default = $this->_currencies[$currency];
} elseif (is_string($currency)) {
$options['before'] = $currency;
}
$options = array_merge($default, $options);
if (isset($options['before']) && $options['before'] !== '') {
$options['wholeSymbol'] = $options['before'];
}
if (isset($options['after']) && !$options['after'] !== '') {
$options['fractionSymbol'] = $options['after'];
}
$result = $options['before'] = $options['after'] = null;
$symbolKey = 'whole';
if ($number == 0 ) {
if ($options['zero'] !== 0 ) {
return $options['zero'];
}
} elseif ($number < 1 && $number > -1 ) {
if ($options['fractionSymbol'] !== false) {
$multiply = intval('1' . str_pad('', $options['places'], '0'));
$number = $number * $multiply;
$options['places'] = null;
$symbolKey = 'fraction';
}
}
$position = $options[$symbolKey.'Position'] != 'after' ? 'before' : 'after';
$options[$position] = $options[$symbolKey.'Symbol'];
$abs = abs($number);
$result = $this->format($abs, $options);
if ($number < 0 ) {
if ($options['negative'] == '()') {
$result = '(' . $result .')';
} else {
$result = $options['negative'] . $result;
}
}
return $result;
return $this->_CakeNumber->currency($number, $currency, $options);
}
/**
* Add a currency format to the Number helper. Makes reusing
* currency formats easier.
*
* {{{ $number->addFormat('NOK', array('before' => 'Kr. ')); }}}
*
* You can now use `NOK` as a shortform when formatting currency amounts.
*
* {{{ $number->currency($value, 'NOK'); }}}
*
* Added formats are merged with the following defaults.
*
* {{{
* array(
* 'before' => '$', 'after' => 'c', 'zero' => 0, 'places' => 2, 'thousands' => ',',
* 'decimals' => '.', 'negative' => '()', 'escape' => true
* )
* }}}
* @see: CakeNumber::addFormat()
*
* @param string $formatName The format name to be used in the future.
* @param array $options The array of options for this format.
@ -250,7 +126,7 @@ class NumberHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::addFormat
*/
public function addFormat($formatName, $options) {
$this->_currencies[$formatName] = $options + $this->_currencyDefaults;
return $this->_CakeNumber->addFormat($formatName, $options);
}
}

View file

@ -20,8 +20,6 @@
*/
App::uses('AppHelper', 'View/Helper');
App::uses('HtmlHelper', 'Helper');
App::uses('Multibyte', 'I18n');
/**
* Text helper library.
@ -31,6 +29,7 @@ App::uses('Multibyte', 'I18n');
* @package Cake.View.Helper
* @property HtmlHelper $Html
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html
* @see String
*/
class TextHelper extends AppHelper {
@ -50,66 +49,26 @@ class TextHelper extends AppHelper {
protected $_placeholders = array();
/**
* Highlights a given phrase in a text. You can specify any expression in highlighter that
* may include the \1 expression to include the $phrase found.
*
* ### Options:
*
* - `format` The piece of html with that the phrase will be highlighted
* - `html` If true, will ignore any HTML tags, ensuring that only the correct text is highlighted
*
* @param string $text Text to search the phrase in
* @param string $phrase The phrase that will be searched
* @param array $options An array of html attributes and options.
* @return string The highlighted text
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::highlight
* String utility instance
*/
public function highlight($text, $phrase, $options = array()) {
if (empty($phrase)) {
return $text;
}
$default = array(
'format' => '<span class="highlight">\1</span>',
'html' => false
);
$options = array_merge($default, $options);
extract($options);
if (is_array($phrase)) {
$replace = array();
$with = array();
foreach ($phrase as $key => $segment) {
$segment = '(' . preg_quote($segment, '|') . ')';
if ($html) {
$segment = "(?![^<]+>)$segment(?![^<]+>)";
}
$with[] = (is_array($format)) ? $format[$key] : $format;
$replace[] = "|$segment|iu";
}
return preg_replace($replace, $with, $text);
} else {
$phrase = '(' . preg_quote($phrase, '|') . ')';
if ($html) {
$phrase = "(?![^<]+>)$phrase(?![^<]+>)";
}
return preg_replace("|$phrase|iu", $format, $text);
}
}
protected $_String;
/**
* Strips given text of all links (<a href=....)
* Constructor
*
* @param string $text Text
* @return string The text without links
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::stripLinks
* @param View $View the view object the helper is attached to.
* @param array $settings Settings array Settings array
*/
public function stripLinks($text) {
return preg_replace('|<a\s+[^>]+>|im', '', preg_replace('|<\/a>|im', '', $text));
public function __construct(View $View, $settings = array()) {
parent::__construct($View, $settings);
$this->_String = new String($settings);
}
/**
* Call methods from String utility class
*/
public function __call($method, $params) {
return call_user_func_array(array($this->_String, $method), $params);
}
/**
@ -239,16 +198,31 @@ class TextHelper extends AppHelper {
}
/**
* Truncates text.
* @see String::highlight()
*
* Cuts a string to the length of $length and replaces the last characters
* with the ending if the text is longer than length.
* @param string $text Text to search the phrase in
* @param string $phrase The phrase that will be searched
* @param array $options An array of html attributes and options.
* @return string The highlighted text
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::highlight
*/
public function highlight($text, $phrase, $options = array()) {
return $this->_String->highlight($text, $phrase, $options);
}
/**
* @see String::stripLinks()
*
* ### Options:
*
* - `ending` Will be used as Ending and appended to the trimmed string
* - `exact` If false, $text will not be cut mid-word
* - `html` If true, HTML tags would be handled correctly
* @param string $text Text
* @return string The text without links
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::stripLinks
*/
public function stripLinks($text) {
return $this->_String->stripLinks($text);
}
/**
* @see String::truncate()
*
* @param string $text String to truncate.
* @param integer $length Length of returned string, including ellipsis.
@ -257,113 +231,11 @@ class TextHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::truncate
*/
public function truncate($text, $length = 100, $options = array()) {
$default = array(
'ending' => '...', 'exact' => true, 'html' => false
);
$options = array_merge($default, $options);
extract($options);
if (!function_exists('mb_strlen')) {
class_exists('Multibyte');
}
if ($html) {
if (mb_strlen(preg_replace('/<.*?>/', '', $text)) <= $length) {
return $text;
}
$totalLength = mb_strlen(strip_tags($ending));
$openTags = array();
$truncate = '';
preg_match_all('/(<\/?([\w+]+)[^>]*>)?([^<>]*)/', $text, $tags, PREG_SET_ORDER);
foreach ($tags as $tag) {
if (!preg_match('/img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param/s', $tag[2])) {
if (preg_match('/<[\w]+[^>]*>/s', $tag[0])) {
array_unshift($openTags, $tag[2]);
} else if (preg_match('/<\/([\w]+)[^>]*>/s', $tag[0], $closeTag)) {
$pos = array_search($closeTag[1], $openTags);
if ($pos !== false) {
array_splice($openTags, $pos, 1);
}
}
}
$truncate .= $tag[1];
$contentLength = mb_strlen(preg_replace('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', ' ', $tag[3]));
if ($contentLength + $totalLength > $length) {
$left = $length - $totalLength;
$entitiesLength = 0;
if (preg_match_all('/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', $tag[3], $entities, PREG_OFFSET_CAPTURE)) {
foreach ($entities[0] as $entity) {
if ($entity[1] + 1 - $entitiesLength <= $left) {
$left--;
$entitiesLength += mb_strlen($entity[0]);
} else {
break;
}
}
}
$truncate .= mb_substr($tag[3], 0 , $left + $entitiesLength);
break;
} else {
$truncate .= $tag[3];
$totalLength += $contentLength;
}
if ($totalLength >= $length) {
break;
}
}
} else {
if (mb_strlen($text) <= $length) {
return $text;
} else {
$truncate = mb_substr($text, 0, $length - mb_strlen($ending));
}
}
if (!$exact) {
$spacepos = mb_strrpos($truncate, ' ');
if ($html) {
$truncateCheck = mb_substr($truncate, 0, $spacepos);
$lastOpenTag = mb_strrpos($truncateCheck, '<');
$lastCloseTag = mb_strrpos($truncateCheck, '>');
if ($lastOpenTag > $lastCloseTag) {
preg_match_all('/<[\w]+[^>]*>/s', $truncate, $lastTagMatches);
$lastTag = array_pop($lastTagMatches[0]);
$spacepos = mb_strrpos($truncate, $lastTag) + mb_strlen($lastTag);
}
$bits = mb_substr($truncate, $spacepos);
preg_match_all('/<\/([a-z]+)>/', $bits, $droppedTags, PREG_SET_ORDER);
if (!empty($droppedTags)) {
if (!empty($openTags)) {
foreach ($droppedTags as $closingTag) {
if (!in_array($closingTag[1], $openTags)) {
array_unshift($openTags, $closingTag[1]);
}
}
} else {
foreach ($droppedTags as $closingTag) {
array_push($openTags, $closingTag[1]);
}
}
}
}
$truncate = mb_substr($truncate, 0, $spacepos);
}
$truncate .= $ending;
if ($html) {
foreach ($openTags as $tag) {
$truncate .= '</' . $tag . '>';
}
}
return $truncate;
return $this->_String->truncate($text, $length, $options);
}
/**
* Extracts an excerpt from the text surrounding the phrase with a number of characters on each side
* determined by radius.
* @see String::excerpt()
*
* @param string $text String to search the phrase in
* @param string $phrase Phrase that will be searched for
@ -373,40 +245,11 @@ class TextHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::excerpt
*/
public function excerpt($text, $phrase, $radius = 100, $ending = '...') {
if (empty($text) or empty($phrase)) {
return $this->truncate($text, $radius * 2, array('ending' => $ending));
}
$append = $prepend = $ending;
$phraseLen = mb_strlen($phrase);
$textLen = mb_strlen($text);
$pos = mb_strpos(mb_strtolower($text), mb_strtolower($phrase));
if ($pos === false) {
return mb_substr($text, 0, $radius) . $ending;
}
$startPos = $pos - $radius;
if ($startPos <= 0) {
$startPos = 0;
$prepend = '';
}
$endPos = $pos + $phraseLen + $radius;
if ($endPos >= $textLen) {
$endPos = $textLen;
$append = '';
}
$excerpt = mb_substr($text, $startPos, $endPos - $startPos);
$excerpt = $prepend . $excerpt . $append;
return $excerpt;
return $this->_String->excerpt($text, $phrase, $radius, $ending);
}
/**
* Creates a comma separated list where the last two items are joined with 'and', forming natural English
* @see String::toList()
*
* @param array $list The list to be joined
* @param string $and The word used to join the last and second last items together with. Defaults to 'and'
@ -415,10 +258,7 @@ class TextHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/text.html#TextHelper::toList
*/
public function toList($list, $and = 'and', $separator = ', ') {
if (count($list) > 1) {
return implode($separator, array_slice($list, null, -1)) . ' ' . $and . ' ' . array_pop($list);
} else {
return array_pop($list);
}
return $this->_String->toList($list, $and, $separator);
}
}

View file

@ -17,6 +17,7 @@
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::uses('CakeTime', 'Utility');
App::uses('Multibyte', 'I18n');
App::uses('AppHelper', 'View/Helper');
@ -27,19 +28,14 @@ App::uses('AppHelper', 'View/Helper');
*
* @package Cake.View.Helper
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html
* @see CakeTime
*/
class TimeHelper extends AppHelper {
/**
* The format to use when formatting a time using `TimeHelper::nice()`
*
* The format should use the locale strings as defined in the PHP docs under
* `strftime` (http://php.net/manual/en/function.strftime.php)
*
* @var string
* @see TimeHelper::format()
* CakeTime instance
*/
public $niceFormat = '%a, %b %eS %Y, %H:%M';
protected $_CakeTime = null;
/**
* Constructor
@ -48,15 +44,69 @@ class TimeHelper extends AppHelper {
* @param array $settings Settings array Settings array
*/
public function __construct(View $View, $settings = array()) {
if (isset($settings['niceFormat'])) {
$this->niceFormat = $settings['niceFormat'];
}
parent::__construct($View, $settings);
$this->_CakeTime = new CakeTime($settings);
}
/**
* Converts a string representing the format for the function strftime and returns a
* windows safe and i18n aware format.
* Magic accessor for deprecated attributes.
*
* @param string $name Name of the attribute to set.
* @param string $value Value of the attribute to set.
* @return mixed
*/
public function __set($name, $value) {
switch ($name) {
case 'niceFormat':
$this->_CakeTime->{$name} = $value; break;
default:
$this->{$name} = $value; break;
}
}
/**
* Magic isset check for deprecated attributes.
*
* @param string $name Name of the attribute to check.
* @return boolean
*/
public function __isset($name) {
if (isset($this->{$name})) {
return true;
}
$magicGet = array('niceFormat');
if (in_array($name, $magicGet)) {
return $this->__get($name) !== null;
}
return null;
}
/**
* Magic accessor for attributes that were deprecated.
*
* @param string $name Name of the attribute to get.
* @return mixed
*/
public function __get($name) {
if (isset($this->_CakeTime->{$name})) {
return $this->_CakeTime->{$name};
}
$magicGet = array('niceFormat');
if (in_array($name, $magicGet)) {
return $this->_CakeTime->{$name};
}
return null;
}
/**
* Call methods from CakeTime utility class
*/
public function __call($method, $params) {
return call_user_func_array(array($this->_CakeTime, $method), $params);
}
/**
* @see CakeTime::convertSpecifiers()
*
* @param string $format Format with specifiers for strftime function.
* Accepts the special specifier %S which mimics the modifier S for date()
@ -65,112 +115,11 @@ class TimeHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function convertSpecifiers($format, $time = null) {
if (!$time) {
$time = time();
}
$this->__time = $time;
return preg_replace_callback('/\%(\w+)/', array($this, '_translateSpecifier'), $format);
return $this->_CakeTime->convertSpecifiers($format, $time);
}
/**
* Auxiliary function to translate a matched specifier element from a regular expression into
* a windows safe and i18n aware specifier
*
* @param array $specifier match from regular expression
* @return string converted element
*/
protected function _translateSpecifier($specifier) {
switch ($specifier[1]) {
case 'a':
$abday = __dc('cake', 'abday', 5);
if (is_array($abday)) {
return $abday[date('w', $this->__time)];
}
break;
case 'A':
$day = __dc('cake', 'day', 5);
if (is_array($day)) {
return $day[date('w', $this->__time)];
}
break;
case 'c':
$format = __dc('cake', 'd_t_fmt', 5);
if ($format != 'd_t_fmt') {
return $this->convertSpecifiers($format, $this->__time);
}
break;
case 'C':
return sprintf("%02d", date('Y', $this->__time) / 100);
case 'D':
return '%m/%d/%y';
case 'e':
if (DS === '/') {
return '%e';
}
$day = date('j', $this->__time);
if ($day < 10) {
$day = ' ' . $day;
}
return $day;
case 'eS' :
return date('jS', $this->__time);
case 'b':
case 'h':
$months = __dc('cake', 'abmon', 5);
if (is_array($months)) {
return $months[date('n', $this->__time) -1];
}
return '%b';
case 'B':
$months = __dc('cake', 'mon', 5);
if (is_array($months)) {
return $months[date('n', $this->__time) -1];
}
break;
case 'n':
return "\n";
case 'p':
case 'P':
$default = array('am' => 0, 'pm' => 1);
$meridiem = $default[date('a', $this->__time)];
$format = __dc('cake', 'am_pm', 5);
if (is_array($format)) {
$meridiem = $format[$meridiem];
return ($specifier[1] == 'P') ? strtolower($meridiem) : strtoupper($meridiem);
}
break;
case 'r':
$complete = __dc('cake', 't_fmt_ampm', 5);
if ($complete != 't_fmt_ampm') {
return str_replace('%p', $this->_translateSpecifier(array('%p', 'p')), $complete);
}
break;
case 'R':
return date('H:i', $this->__time);
case 't':
return "\t";
case 'T':
return '%H:%M:%S';
case 'u':
return ($weekDay = date('w', $this->__time)) ? $weekDay : 7;
case 'x':
$format = __dc('cake', 'd_fmt', 5);
if ($format != 'd_fmt') {
return $this->convertSpecifiers($format, $this->__time);
}
break;
case 'X':
$format = __dc('cake', 't_fmt', 5);
if ($format != 't_fmt') {
return $this->convertSpecifiers($format, $this->__time);
}
break;
}
return $specifier[0];
}
/**
* Converts given time (in server's time zone) to user's local time, given his/her offset from GMT.
* @see CakeTime::convert()
*
* @param string $serverTime UNIX timestamp
* @param integer $userOffset User's offset from GMT (in hours)
@ -178,24 +127,21 @@ class TimeHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function convert($serverTime, $userOffset) {
$serverOffset = $this->serverOffset();
$gmtTime = $serverTime - $serverOffset;
$userTime = $gmtTime + $userOffset * (60*60);
return $userTime;
return $this->_CakeTime->convert($serverTime, $userOffset);
}
/**
* Returns server's offset from GMT in seconds.
* @see CakeTime::serverOffset()
*
* @return integer Offset
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function serverOffset() {
return date('Z', time());
return $this->_CakeTime->serverOffset();
}
/**
* Returns a UNIX timestamp, given either a UNIX timestamp or a valid strtotime() date string.
* @see CakeTime::fromString()
*
* @param string $dateString Datetime string
* @param integer $userOffset User's offset from GMT (in hours)
@ -203,28 +149,11 @@ class TimeHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function fromString($dateString, $userOffset = null) {
if (empty($dateString)) {
return false;
}
if (is_integer($dateString) || is_numeric($dateString)) {
$date = intval($dateString);
} else {
$date = strtotime($dateString);
}
if ($userOffset !== null) {
return $this->convert($date, $userOffset);
}
if ($date === -1) {
return false;
}
return $date;
return $this->_CakeTime->fromString($dateString, $userOffset);
}
/**
* Returns a nicely formatted date string for given Datetime string.
*
* See http://php.net/manual/en/function.strftime.php for information on formatting
* using locale strings.
* @see CakeTime::nice()
*
* @param string $dateString Datetime string or Unix timestamp
* @param integer $userOffset User's offset from GMT (in hours)
@ -233,25 +162,11 @@ class TimeHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function nice($dateString = null, $userOffset = null, $format = null) {
if ($dateString != null) {
$date = $this->fromString($dateString, $userOffset);
} else {
$date = time();
}
if (!$format) {
$format = $this->niceFormat;
}
$format = $this->convertSpecifiers($format, $date);
return $this->_strftime($format, $date);
return $this->_CakeTime->nice($dateString, $userOffset, $format);
}
/**
* Returns a formatted descriptive date string for given datetime string.
*
* If the given date is today, the returned string could be "Today, 16:54".
* If the given date was yesterday, the returned string could be "Yesterday, 16:54".
* If $dateString's year is the current year, the returned string does not
* include mention of the year.
* @see CakeTime::niceShort()
*
* @param string $dateString Datetime string or Unix timestamp
* @param integer $userOffset User's offset from GMT (in hours)
@ -259,24 +174,11 @@ class TimeHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function niceShort($dateString = null, $userOffset = null) {
$date = $dateString ? $this->fromString($dateString, $userOffset) : time();
$y = $this->isThisYear($date) ? '' : ' %Y';
if ($this->isToday($dateString, $userOffset)) {
$ret = __d('cake', 'Today, %s', $this->_strftime("%H:%M", $date));
} elseif ($this->wasYesterday($dateString, $userOffset)) {
$ret = __d('cake', 'Yesterday, %s', $this->_strftime("%H:%M", $date));
} else {
$format = $this->convertSpecifiers("%b %eS{$y}, %H:%M", $date);
$ret = $this->_strftime($format, $date);
}
return $ret;
return $this->_CakeTime->niceShort($dateString, $userOffset);
}
/**
* Returns a partial SQL string to search for all records between two dates.
* @see CakeTime::daysAsSql()
*
* @param string $begin Datetime string or Unix timestamp
* @param string $end Datetime string or Unix timestamp
@ -286,17 +188,11 @@ class TimeHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function daysAsSql($begin, $end, $fieldName, $userOffset = null) {
$begin = $this->fromString($begin, $userOffset);
$end = $this->fromString($end, $userOffset);
$begin = date('Y-m-d', $begin) . ' 00:00:00';
$end = date('Y-m-d', $end) . ' 23:59:59';
return "($fieldName >= '$begin') AND ($fieldName <= '$end')";
return $this->_CakeTime->daysAsSql($begin, $end, $fieldName, $userOffset);
}
/**
* Returns a partial SQL string to search for all records between two times
* occurring on the same day.
* @see CakeTime::dayAsSql()
*
* @param string $dateString Datetime string or Unix timestamp
* @param string $fieldName Name of database field to compare with
@ -305,12 +201,11 @@ class TimeHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function dayAsSql($dateString, $fieldName, $userOffset = null) {
$date = $this->fromString($dateString, $userOffset);
return $this->daysAsSql($dateString, $dateString, $fieldName);
return $this->_CakeTime->dayAsSql($dateString, $fieldName, $userOffset);
}
/**
* Returns true if given datetime string is today.
* @see CakeTime::isToday()
*
* @param string $dateString Datetime string or Unix timestamp
* @param integer $userOffset User's offset from GMT (in hours)
@ -318,12 +213,11 @@ class TimeHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#testing-time
*/
public function isToday($dateString, $userOffset = null) {
$date = $this->fromString($dateString, $userOffset);
return date('Y-m-d', $date) == date('Y-m-d', time());
return $this->_CakeTime->isToday($dateString, $userOffset);
}
/**
* Returns true if given datetime string is within this week.
* @see CakeTime::isThisWeek()
*
* @param string $dateString
* @param integer $userOffset User's offset from GMT (in hours)
@ -331,24 +225,23 @@ class TimeHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#testing-time
*/
public function isThisWeek($dateString, $userOffset = null) {
$date = $this->fromString($dateString, $userOffset);
return date('W o', $date) == date('W o', time());
return $this->_CakeTime->isThisWeek($dateString, $userOffset);
}
/**
* Returns true if given datetime string is within this month
* @see CakeTime::isThisMonth()
*
* @param string $dateString
* @param integer $userOffset User's offset from GMT (in hours)
* @return boolean True if datetime string is within current month
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#testing-time
*/
public function isThisMonth($dateString, $userOffset = null) {
$date = $this->fromString($dateString);
return date('m Y', $date) == date('m Y', time());
return $this->_CakeTime->isThisMonth($dateString, $userOffset);
}
/**
* Returns true if given datetime string is within current year.
* @see CakeTime::isThisYear()
*
* @param string $dateString Datetime string or Unix timestamp
* @param integer $userOffset User's offset from GMT (in hours)
@ -356,12 +249,11 @@ class TimeHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#testing-time
*/
public function isThisYear($dateString, $userOffset = null) {
$date = $this->fromString($dateString, $userOffset);
return date('Y', $date) == date('Y', time());
return $this->_CakeTime->isThisYear($dateString, $userOffset);
}
/**
* Returns true if given datetime string was yesterday.
* @see CakeTime::wasYesterday()
*
* @param string $dateString Datetime string or Unix timestamp
* @param integer $userOffset User's offset from GMT (in hours)
@ -370,12 +262,11 @@ class TimeHelper extends AppHelper {
*
*/
public function wasYesterday($dateString, $userOffset = null) {
$date = $this->fromString($dateString, $userOffset);
return date('Y-m-d', $date) == date('Y-m-d', strtotime('yesterday'));
return $this->_CakeTime->wasYesterday($dateString, $userOffset);
}
/**
* Returns true if given datetime string is tomorrow.
* @see CakeTime::isTomorrow()
*
* @param string $dateString Datetime string or Unix timestamp
* @param integer $userOffset User's offset from GMT (in hours)
@ -383,12 +274,11 @@ class TimeHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#testing-time
*/
public function isTomorrow($dateString, $userOffset = null) {
$date = $this->fromString($dateString, $userOffset);
return date('Y-m-d', $date) == date('Y-m-d', strtotime('tomorrow'));
return $this->_CakeTime->isTomorrow($dateString, $userOffset);
}
/**
* Returns the quarter
* @see CakeTime::toQuarter()
*
* @param string $dateString
* @param boolean $range if true returns a range in Y-m-d format
@ -396,36 +286,11 @@ class TimeHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function toQuarter($dateString, $range = false) {
$time = $this->fromString($dateString);
$date = ceil(date('m', $time) / 3);
if ($range === true) {
$range = 'Y-m-d';
}
if ($range !== false) {
$year = date('Y', $time);
switch ($date) {
case 1:
$date = array($year.'-01-01', $year.'-03-31');
break;
case 2:
$date = array($year.'-04-01', $year.'-06-30');
break;
case 3:
$date = array($year.'-07-01', $year.'-09-30');
break;
case 4:
$date = array($year.'-10-01', $year.'-12-31');
break;
}
}
return $date;
return $this->_CakeTime->toQuarter($dateString, $range);
}
/**
* Returns a UNIX timestamp from a textual datetime description. Wrapper for PHP function strtotime().
* @see CakeTime::toUnix()
*
* @param string $dateString Datetime string to be represented as a Unix timestamp
* @param integer $userOffset User's offset from GMT (in hours)
@ -433,11 +298,11 @@ class TimeHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function toUnix($dateString, $userOffset = null) {
return $this->fromString($dateString, $userOffset);
return $this->_CakeTime->toUnix($dateString, $userOffset);
}
/**
* Returns a date formatted for Atom RSS feeds.
* @see CakeTime::toAtom()
*
* @param string $dateString Datetime string or Unix timestamp
* @param integer $userOffset User's offset from GMT (in hours)
@ -445,12 +310,11 @@ class TimeHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function toAtom($dateString, $userOffset = null) {
$date = $this->fromString($dateString, $userOffset);
return date('Y-m-d\TH:i:s\Z', $date);
return $this->_CakeTime->toAtom($dateString, $userOffset);
}
/**
* Formats date for RSS feeds
* @see CakeTime::toRSS()
*
* @param string $dateString Datetime string or Unix timestamp
* @param integer $userOffset User's offset from GMT (in hours)
@ -458,40 +322,11 @@ class TimeHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function toRSS($dateString, $userOffset = null) {
$date = $this->fromString($dateString, $userOffset);
if (!is_null($userOffset)) {
if ($userOffset == 0) {
$timezone = '+0000';
} else {
$hours = (int) floor(abs($userOffset));
$minutes = (int) (fmod(abs($userOffset), $hours) * 60);
$timezone = ($userOffset < 0 ? '-' : '+') . str_pad($hours, 2, '0', STR_PAD_LEFT) . str_pad($minutes, 2, '0', STR_PAD_LEFT);
}
return date('D, d M Y H:i:s', $date) . ' ' . $timezone;
}
return date("r", $date);
return $this->_CakeTime->toRSS($dateString, $userOffset);
}
/**
* Returns either a relative date or a formatted date depending
* on the difference between the current time and given datetime.
* $datetime should be in a <i>strtotime</i> - parsable format, like MySQL's datetime datatype.
*
* ### Options:
*
* - `format` => a fall back format if the relative time is longer than the duration specified by end
* - `end` => The end of relative time telling
* - `userOffset` => Users offset from GMT (in hours)
*
* Relative dates look something like this:
* 3 weeks, 4 days ago
* 15 seconds ago
*
* Default date formatting is d/m/yy e.g: on 18/2/09
*
* The returned string includes 'ago' or 'on' and assumes you'll properly add a word
* like 'Posted ' before the function output.
* @see CakeTime::timeAgoInWords()
*
* @param string $dateTime Datetime string or Unix timestamp
* @param array $options Default format if timestamp is used in $dateString
@ -499,163 +334,11 @@ class TimeHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function timeAgoInWords($dateTime, $options = array()) {
$userOffset = null;
if (is_array($options) && isset($options['userOffset'])) {
$userOffset = $options['userOffset'];
}
$now = time();
if (!is_null($userOffset)) {
$now = $this->convert(time(), $userOffset);
}
$inSeconds = $this->fromString($dateTime, $userOffset);
$backwards = ($inSeconds > $now);
$format = 'j/n/y';
$end = '+1 month';
if (is_array($options)) {
if (isset($options['format'])) {
$format = $options['format'];
unset($options['format']);
}
if (isset($options['end'])) {
$end = $options['end'];
unset($options['end']);
}
} else {
$format = $options;
}
if ($backwards) {
$futureTime = $inSeconds;
$pastTime = $now;
} else {
$futureTime = $now;
$pastTime = $inSeconds;
}
$diff = $futureTime - $pastTime;
// If more than a week, then take into account the length of months
if ($diff >= 604800) {
$current = array();
$date = array();
list($future['H'], $future['i'], $future['s'], $future['d'], $future['m'], $future['Y']) = explode('/', date('H/i/s/d/m/Y', $futureTime));
list($past['H'], $past['i'], $past['s'], $past['d'], $past['m'], $past['Y']) = explode('/', date('H/i/s/d/m/Y', $pastTime));
$years = $months = $weeks = $days = $hours = $minutes = $seconds = 0;
if ($future['Y'] == $past['Y'] && $future['m'] == $past['m']) {
$months = 0;
$years = 0;
} else {
if ($future['Y'] == $past['Y']) {
$months = $future['m'] - $past['m'];
} else {
$years = $future['Y'] - $past['Y'];
$months = $future['m'] + ((12 * $years) - $past['m']);
if ($months >= 12) {
$years = floor($months / 12);
$months = $months - ($years * 12);
}
if ($future['m'] < $past['m'] && $future['Y'] - $past['Y'] == 1) {
$years --;
}
}
}
if ($future['d'] >= $past['d']) {
$days = $future['d'] - $past['d'];
} else {
$daysInPastMonth = date('t', $pastTime);
$daysInFutureMonth = date('t', mktime(0, 0, 0, $future['m'] - 1, 1, $future['Y']));
if (!$backwards) {
$days = ($daysInPastMonth - $past['d']) + $future['d'];
} else {
$days = ($daysInFutureMonth - $past['d']) + $future['d'];
}
if ($future['m'] != $past['m']) {
$months --;
}
}
if ($months == 0 && $years >= 1 && $diff < ($years * 31536000)) {
$months = 11;
$years --;
}
if ($months >= 12) {
$years = $years + 1;
$months = $months - 12;
}
if ($days >= 7) {
$weeks = floor($days / 7);
$days = $days - ($weeks * 7);
}
} else {
$years = $months = $weeks = 0;
$days = floor($diff / 86400);
$diff = $diff - ($days * 86400);
$hours = floor($diff / 3600);
$diff = $diff - ($hours * 3600);
$minutes = floor($diff / 60);
$diff = $diff - ($minutes * 60);
$seconds = $diff;
}
$relativeDate = '';
$diff = $futureTime - $pastTime;
if ($diff > abs($now - $this->fromString($end))) {
$relativeDate = __d('cake', 'on %s', date($format, $inSeconds));
} else {
if ($years > 0) {
// years and months and days
$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d year', '%d years', $years, $years);
$relativeDate .= $months > 0 ? ($relativeDate ? ', ' : '') . __dn('cake', '%d month', '%d months', $months, $months) : '';
$relativeDate .= $weeks > 0 ? ($relativeDate ? ', ' : '') . __dn('cake', '%d week', '%d weeks', $weeks, $weeks) : '';
$relativeDate .= $days > 0 ? ($relativeDate ? ', ' : '') . __dn('cake', '%d day', '%d days', $days, $days) : '';
} elseif (abs($months) > 0) {
// months, weeks and days
$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d month', '%d months', $months, $months);
$relativeDate .= $weeks > 0 ? ($relativeDate ? ', ' : '') . __dn('cake', '%d week', '%d weeks', $weeks, $weeks) : '';
$relativeDate .= $days > 0 ? ($relativeDate ? ', ' : '') . __dn('cake', '%d day', '%d days', $days, $days) : '';
} elseif (abs($weeks) > 0) {
// weeks and days
$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d week', '%d weeks', $weeks, $weeks);
$relativeDate .= $days > 0 ? ($relativeDate ? ', ' : '') . __dn('cake', '%d day', '%d days', $days, $days) : '';
} elseif (abs($days) > 0) {
// days and hours
$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d day', '%d days', $days, $days);
$relativeDate .= $hours > 0 ? ($relativeDate ? ', ' : '') . __dn('cake', '%d hour', '%d hours', $hours, $hours) : '';
} elseif (abs($hours) > 0) {
// hours and minutes
$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d hour', '%d hours', $hours, $hours);
$relativeDate .= $minutes > 0 ? ($relativeDate ? ', ' : '') . __dn('cake', '%d minute', '%d minutes', $minutes, $minutes) : '';
} elseif (abs($minutes) > 0) {
// minutes only
$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d minute', '%d minutes', $minutes, $minutes);
} else {
// seconds only
$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d second', '%d seconds', $seconds, $seconds);
}
if (!$backwards) {
$relativeDate = __d('cake', '%s ago', $relativeDate);
}
}
return $relativeDate;
return $this->_CakeTime->timeAgoInWords($dateTime, $options);
}
/**
* Returns true if specified datetime was within the interval specified, else false.
* @see CakeTime::wasWithinLast()
*
* @param mixed $timeInterval the numeric value with space then time type.
* Example of valid types: 6 hours, 2 days, 1 minute.
@ -665,48 +348,22 @@ class TimeHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#testing-time
*/
public function wasWithinLast($timeInterval, $dateString, $userOffset = null) {
$tmp = str_replace(' ', '', $timeInterval);
if (is_numeric($tmp)) {
$timeInterval = $tmp . ' ' . __d('cake', 'days');
}
$date = $this->fromString($dateString, $userOffset);
$interval = $this->fromString('-' . $timeInterval);
if ($date >= $interval && $date <= time()) {
return true;
}
return false;
return $this->_CakeTime->wasWithinLast($timeInterval, $dateString, $userOffset);
}
/**
* Returns gmt as a UNIX timestamp.
* @see CakeTime::gmt()
*
* @param string $string UNIX timestamp or a valid strtotime() date string
* @return integer UNIX timestamp
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function gmt($string = null) {
if ($string != null) {
$string = $this->fromString($string);
} else {
$string = time();
}
$hour = intval(date("G", $string));
$minute = intval(date("i", $string));
$second = intval(date("s", $string));
$month = intval(date("n", $string));
$day = intval(date("j", $string));
$year = intval(date("Y", $string));
return gmmktime($hour, $minute, $second, $month, $day, $year);
return $this->_CakeTime->gmt($string);
}
/**
* Returns a formatted date string, given either a UNIX timestamp or a valid strtotime() date string.
* This function also accepts a time string and a format string as first and second parameters.
* In that case this function behaves as a wrapper for TimeHelper::i18nFormat()
* @see CakeTime::format()
*
* @param string $format date format string (or a DateTime string)
* @param string $date Datetime string (or a date format string)
@ -716,22 +373,11 @@ class TimeHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function format($format, $date = null, $invalid = false, $userOffset = null) {
$time = $this->fromString($date, $userOffset);
$_time = $this->fromString($format, $userOffset);
if (is_numeric($_time) && $time === false) {
$format = $date;
return $this->i18nFormat($_time, $format, $invalid, $userOffset);
}
if ($time === false && $invalid !== false) {
return $invalid;
}
return date($format, $time);
return $this->_CakeTime->format($format, $date, $invalid, $userOffset);
}
/**
* Returns a formatted date string, given either a UNIX timestamp or a valid strtotime() date string.
* It take in account the default date format for the current language if a LC_TIME file is used.
* @see CakeTime::i18nFormat()
*
* @param string $date Datetime string
* @param string $format strftime format string.
@ -741,40 +387,7 @@ class TimeHelper extends AppHelper {
* @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#formatting
*/
public function i18nFormat($date, $format = null, $invalid = false, $userOffset = null) {
$date = $this->fromString($date, $userOffset);
if ($date === false && $invalid !== false) {
return $invalid;
}
if (empty($format)) {
$format = '%x';
}
$format = $this->convertSpecifiers($format, $date);
return $this->_strftime($format, $date);
return $this->_CakeTime->i18nFormat($date, $format, $invalid, $userOffset);
}
/**
* Multibyte wrapper for strftime.
*
* Handles utf8_encoding the result of strftime when necessary.
*
* @param string $format Format string.
* @param int $date Timestamp to format.
* @return string formatted string with correct encoding.
*/
protected function _strftime($format, $date) {
$format = strftime($format, $date);
$encoding = Configure::read('App.encoding');
if (!empty($encoding) && $encoding === 'UTF-8') {
if (function_exists('mb_check_encoding')) {
$valid = mb_check_encoding($format, $encoding);
} else {
$valid = !Multibyte::checkMultibyte($format);
}
if (!$valid) {
$format = utf8_encode($format);
}
}
return $format;
}
}

View file

@ -31,9 +31,11 @@ App::uses('CakeRequest', 'Network');
* - `id` The filename on the server's filesystem, including extension.
* - `name` The filename that will be sent to the user, specified without the extension.
* - `download` Set to true to set a `Content-Disposition` header. This is ideal for file downloads.
* - `extension` The extension of the file being served. This is used to set the mimetype
* - `extension` The extension of the file being served. This is used to set the mimetype.
* If not provided its extracted from filename provided as `id`.
* - `path` The absolute path, including the trailing / on the server's filesystem to `id`.
* - `mimeType` The mime type of the file if CakeResponse doesn't know about it.
* Must be an associative array with extension as key and mime type as value eg. array('ini' => 'text/plain')
*
* ### Usage
*
@ -101,7 +103,11 @@ class MediaView extends View {
$this->response->type($mimeType);
}
if (isset($extension) && $this->_isActive()) {
if (!isset($extension)) {
$extension = pathinfo($id, PATHINFO_EXTENSION);
}
if ($this->_isActive()) {
$extension = strtolower($extension);
$chunkSize = 8192;
$buffer = '';
@ -116,7 +122,7 @@ class MediaView extends View {
} else {
$modified = time();
}
if ($this->response->type($extension) === false) {
if (!$extension || $this->response->type($extension) === false) {
$download = true;
}
@ -145,6 +151,8 @@ class MediaView extends View {
}
if (is_null($name)) {
$name = $id;
} elseif ($extension) {
$name .= '.' . $extension;
}
$this->response->download($name);
$this->response->header(array('Accept-Ranges' => 'bytes'));

View file

@ -23,6 +23,10 @@ define('TIME_START', microtime(true));
if (!defined('E_DEPRECATED')) {
define('E_DEPRECATED', 8192);
}
if (!defined('E_USER_DEPRECATED')) {
define('E_USER_DEPRECATED', E_USER_NOTICE);
}
error_reporting(E_ALL & ~E_DEPRECATED);
if (!defined('CAKE_CORE_INCLUDE_PATH')) {